mfkey32.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. #pragma GCC optimize("O3")
  2. #pragma GCC optimize("-funroll-all-loops")
  3. // TODO: Add keys to top of the user dictionary, not the bottom
  4. // TODO: More efficient dictionary bruteforce by scanning through hardcoded very common keys and previously found dictionary keys first?
  5. // (a cache for napi_key_already_found_for_nonce)
  6. #include <furi.h>
  7. #include <furi_hal.h>
  8. #include "time.h"
  9. #include <gui/gui.h>
  10. #include <gui/elements.h>
  11. #include <input/input.h>
  12. #include <stdlib.h>
  13. #include "mfkey32_icons.h"
  14. #include <inttypes.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdint.h>
  18. #include <unistd.h>
  19. #include <storage/storage.h>
  20. #include <toolbox/stream/buffered_file_stream.h>
  21. #include <lib/toolbox/args.h>
  22. #include <lib/flipper_format/flipper_format.h>
  23. #include <dolphin/dolphin.h>
  24. #include <notification/notification_messages.h>
  25. #define MF_CLASSIC_DICT_FLIPPER_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc")
  26. #define MF_CLASSIC_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc")
  27. #define MF_CLASSIC_NONCE_PATH EXT_PATH("nfc/.mfkey32.log")
  28. #define TAG "Mfkey32"
  29. #define NFC_MF_CLASSIC_KEY_LEN (13)
  30. #define MIN_RAM 115632
  31. #define LF_POLY_ODD (0x29CE5C)
  32. #define LF_POLY_EVEN (0x870804)
  33. #define CONST_M1_1 (LF_POLY_EVEN << 1 | 1)
  34. #define CONST_M2_1 (LF_POLY_ODD << 1)
  35. #define CONST_M1_2 (LF_POLY_ODD)
  36. #define CONST_M2_2 (LF_POLY_EVEN << 1 | 1)
  37. #define BIT(x, n) ((x) >> (n) & 1)
  38. #define BEBIT(x, n) BIT(x, (n) ^ 24)
  39. #define SWAPENDIAN(x) \
  40. ((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16)
  41. //#define SIZEOF(arr) sizeof(arr) / sizeof(*arr)
  42. static int eta_round_time = 56;
  43. static int eta_total_time = 900;
  44. // MSB_LIMIT: Chunk size (out of 256)
  45. static int MSB_LIMIT = 16;
  46. struct Crypto1State {
  47. uint32_t odd, even;
  48. };
  49. struct Crypto1Params {
  50. uint64_t key;
  51. uint32_t nr0_enc, uid_xor_nt0, uid_xor_nt1, nr1_enc, p64b, ar1_enc;
  52. };
  53. struct Msb {
  54. int tail;
  55. uint32_t states[768];
  56. };
  57. typedef enum {
  58. EventTypeTick,
  59. EventTypeKey,
  60. } EventType;
  61. typedef struct {
  62. EventType type;
  63. InputEvent input;
  64. } PluginEvent;
  65. typedef enum {
  66. MissingNonces,
  67. ZeroNonces,
  68. } MfkeyError;
  69. typedef enum {
  70. Ready,
  71. Initializing,
  72. DictionaryAttack,
  73. MfkeyAttack,
  74. Complete,
  75. Error,
  76. Help,
  77. } MfkeyState;
  78. // TODO: Can we eliminate any of the members of this struct?
  79. typedef struct {
  80. FuriMutex* mutex;
  81. MfkeyError err;
  82. MfkeyState mfkey_state;
  83. int cracked;
  84. int unique_cracked;
  85. int num_completed;
  86. int total;
  87. int dict_count;
  88. int search;
  89. int eta_timestamp;
  90. int eta_total;
  91. int eta_round;
  92. bool is_thread_running;
  93. bool close_thread_please;
  94. FuriThread* mfkeythread;
  95. } ProgramState;
  96. // TODO: Merge this with Crypto1Params?
  97. typedef struct {
  98. uint32_t uid; // serial number
  99. uint32_t nt0; // tag challenge first
  100. uint32_t nt1; // tag challenge second
  101. uint32_t nr0_enc; // first encrypted reader challenge
  102. uint32_t ar0_enc; // first encrypted reader response
  103. uint32_t nr1_enc; // second encrypted reader challenge
  104. uint32_t ar1_enc; // second encrypted reader response
  105. } MfClassicNonce;
  106. typedef struct {
  107. Stream* stream;
  108. uint32_t total_nonces;
  109. MfClassicNonce* remaining_nonce_array;
  110. size_t remaining_nonces;
  111. } MfClassicNonceArray;
  112. typedef enum {
  113. MfClassicDictTypeSystem,
  114. MfClassicDictTypeUser,
  115. } MfClassicDictType;
  116. typedef struct {
  117. Stream* stream;
  118. uint32_t total_keys;
  119. } MfClassicDict;
  120. static const uint8_t table[256] = {
  121. 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3,
  122. 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
  123. 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4,
  124. 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,
  125. 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
  126. 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
  127. 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4,
  128. 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6,
  129. 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
  130. static const uint8_t lookup1[256] = {
  131. 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
  132. 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16,
  133. 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8,
  134. 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  135. 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
  136. 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  137. 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
  138. 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  139. 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 0, 0, 16, 16, 0, 16, 0, 0,
  140. 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  141. 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24};
  142. static const uint8_t lookup2[256] = {
  143. 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4,
  144. 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6,
  145. 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2,
  146. 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4,
  147. 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2,
  148. 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4,
  149. 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2,
  150. 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2,
  151. 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6};
  152. uint32_t prng_successor(uint32_t x, uint32_t n) {
  153. SWAPENDIAN(x);
  154. while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
  155. return SWAPENDIAN(x);
  156. }
  157. static inline int filter(uint32_t const x) {
  158. uint32_t f;
  159. f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff];
  160. f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
  161. return BIT(0xEC57E80A, f);
  162. }
  163. static inline uint8_t evenparity32(uint32_t x) {
  164. if((table[x & 0xff] + table[(x >> 8) & 0xff] + table[(x >> 16) & 0xff] + table[x >> 24]) % 2 ==
  165. 0) {
  166. return 0;
  167. } else {
  168. return 1;
  169. }
  170. //return ((table[x & 0xff] + table[(x >> 8) & 0xff] + table[(x >> 16) & 0xff] + table[x >> 24]) % 2) & 0xFF;
  171. }
  172. static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2) {
  173. int p = data[item] >> 25;
  174. p = p << 1 | evenparity32(data[item] & mask1);
  175. p = p << 1 | evenparity32(data[item] & mask2);
  176. data[item] = p << 24 | (data[item] & 0xffffff);
  177. }
  178. void crypto1_get_lfsr(struct Crypto1State* state, uint64_t* lfsr) {
  179. int i;
  180. for(*lfsr = 0, i = 23; i >= 0; --i) {
  181. *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3);
  182. *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3);
  183. }
  184. }
  185. static inline uint32_t crypt_word(struct Crypto1State* s) {
  186. // "in" and "x" are always 0 (last iteration)
  187. uint32_t res_ret = 0;
  188. uint32_t feedin, t;
  189. for(int i = 0; i <= 31; i++) {
  190. res_ret |= (filter(s->odd) << (24 ^ i)); //-V629
  191. feedin = LF_POLY_EVEN & s->even;
  192. feedin ^= LF_POLY_ODD & s->odd;
  193. s->even = s->even << 1 | (evenparity32(feedin));
  194. t = s->odd, s->odd = s->even, s->even = t;
  195. }
  196. return res_ret;
  197. }
  198. static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x) {
  199. uint8_t ret;
  200. uint32_t feedin, t, next_in;
  201. for(int i = 0; i <= 31; i++) {
  202. next_in = BEBIT(in, i);
  203. ret = filter(s->odd);
  204. feedin = ret & (!!x);
  205. feedin ^= LF_POLY_EVEN & s->even;
  206. feedin ^= LF_POLY_ODD & s->odd;
  207. feedin ^= !!next_in;
  208. s->even = s->even << 1 | (evenparity32(feedin));
  209. t = s->odd, s->odd = s->even, s->even = t;
  210. }
  211. return;
  212. }
  213. static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x) {
  214. uint8_t ret;
  215. uint32_t feedin, t, next_in;
  216. for(int i = 31; i >= 0; i--) {
  217. next_in = BEBIT(in, i);
  218. s->odd &= 0xffffff;
  219. t = s->odd, s->odd = s->even, s->even = t;
  220. ret = filter(s->odd);
  221. feedin = ret & (!!x);
  222. feedin ^= s->even & 1;
  223. feedin ^= LF_POLY_EVEN & (s->even >>= 1);
  224. feedin ^= LF_POLY_ODD & s->odd;
  225. feedin ^= !!next_in;
  226. s->even |= (evenparity32(feedin)) << 23;
  227. }
  228. return;
  229. }
  230. int key_already_found_for_nonce(
  231. uint64_t* keyarray,
  232. int keyarray_size,
  233. uint32_t uid_xor_nt1,
  234. uint32_t nr1_enc,
  235. uint32_t p64b,
  236. uint32_t ar1_enc) {
  237. for(int k = 0; k < keyarray_size; k++) {
  238. struct Crypto1State temp = {0, 0};
  239. for(int i = 0; i < 24; i++) {
  240. (&temp)->odd |= (BIT(keyarray[k], 2 * i + 1) << (i ^ 3));
  241. (&temp)->even |= (BIT(keyarray[k], 2 * i) << (i ^ 3));
  242. }
  243. crypt_word_noret(&temp, uid_xor_nt1, 0);
  244. crypt_word_noret(&temp, nr1_enc, 1);
  245. if(ar1_enc == (crypt_word(&temp) ^ p64b)) {
  246. return 1;
  247. }
  248. }
  249. return 0;
  250. }
  251. int check_state(struct Crypto1State* t, struct Crypto1Params* p) {
  252. if(!(t->odd | t->even)) return 0;
  253. rollback_word_noret(t, 0, 0);
  254. rollback_word_noret(t, p->nr0_enc, 1);
  255. rollback_word_noret(t, p->uid_xor_nt0, 0);
  256. struct Crypto1State temp = {t->odd, t->even};
  257. crypt_word_noret(t, p->uid_xor_nt1, 0);
  258. crypt_word_noret(t, p->nr1_enc, 1);
  259. if(p->ar1_enc == (crypt_word(t) ^ p->p64b)) {
  260. crypto1_get_lfsr(&temp, &(p->key));
  261. return 1;
  262. }
  263. return 0;
  264. }
  265. static inline int state_loop(unsigned int* states_buffer, int xks, int m1, int m2) {
  266. int states_tail = 0;
  267. int round = 0, s = 0, xks_bit = 0;
  268. for(round = 1; round <= 12; round++) {
  269. xks_bit = BIT(xks, round);
  270. for(s = 0; s <= states_tail; s++) {
  271. states_buffer[s] <<= 1;
  272. if((filter(states_buffer[s]) ^ filter(states_buffer[s] | 1)) != 0) {
  273. states_buffer[s] |= filter(states_buffer[s]) ^ xks_bit;
  274. if(round > 4) {
  275. update_contribution(states_buffer, s, m1, m2);
  276. }
  277. } else if(filter(states_buffer[s]) == xks_bit) {
  278. // TODO: Refactor
  279. if(round > 4) {
  280. states_buffer[++states_tail] = states_buffer[s + 1];
  281. states_buffer[s + 1] = states_buffer[s] | 1;
  282. update_contribution(states_buffer, s, m1, m2);
  283. s++;
  284. update_contribution(states_buffer, s, m1, m2);
  285. } else {
  286. states_buffer[++states_tail] = states_buffer[++s];
  287. states_buffer[s] = states_buffer[s - 1] | 1;
  288. }
  289. } else {
  290. states_buffer[s--] = states_buffer[states_tail--];
  291. }
  292. }
  293. }
  294. return states_tail;
  295. }
  296. int binsearch(unsigned int data[], int start, int stop) {
  297. int mid, val = data[stop] & 0xff000000;
  298. while(start != stop) {
  299. mid = (stop - start) >> 1;
  300. if((data[start + mid] ^ 0x80000000) > (val ^ 0x80000000))
  301. stop = start + mid;
  302. else
  303. start += mid + 1;
  304. }
  305. return start;
  306. }
  307. void quicksort(unsigned int array[], int low, int high) {
  308. //if (SIZEOF(array) == 0)
  309. // return;
  310. if(low >= high) return;
  311. int middle = low + (high - low) / 2;
  312. unsigned int pivot = array[middle];
  313. int i = low, j = high;
  314. while(i <= j) {
  315. while(array[i] < pivot) {
  316. i++;
  317. }
  318. while(array[j] > pivot) {
  319. j--;
  320. }
  321. if(i <= j) { // swap
  322. int temp = array[i];
  323. array[i] = array[j];
  324. array[j] = temp;
  325. i++;
  326. j--;
  327. }
  328. }
  329. if(low < j) {
  330. quicksort(array, low, j);
  331. }
  332. if(high > i) {
  333. quicksort(array, i, high);
  334. }
  335. }
  336. int extend_table(unsigned int data[], int tbl, int end, int bit, int m1, int m2) {
  337. for(data[tbl] <<= 1; tbl <= end; data[++tbl] <<= 1) {
  338. if((filter(data[tbl]) ^ filter(data[tbl] | 1)) != 0) {
  339. data[tbl] |= filter(data[tbl]) ^ bit;
  340. update_contribution(data, tbl, m1, m2);
  341. } else if(filter(data[tbl]) == bit) {
  342. data[++end] = data[tbl + 1];
  343. data[tbl + 1] = data[tbl] | 1;
  344. update_contribution(data, tbl, m1, m2);
  345. tbl++;
  346. update_contribution(data, tbl, m1, m2);
  347. } else {
  348. data[tbl--] = data[end--];
  349. }
  350. }
  351. return end;
  352. }
  353. int old_recover(
  354. unsigned int odd[],
  355. int o_head,
  356. int o_tail,
  357. int oks,
  358. unsigned int even[],
  359. int e_head,
  360. int e_tail,
  361. int eks,
  362. int rem,
  363. int s,
  364. struct Crypto1Params* p,
  365. int first_run) {
  366. int o, e, i;
  367. if(rem == -1) {
  368. for(e = e_head; e <= e_tail; ++e) {
  369. even[e] = (even[e] << 1) ^ evenparity32(even[e] & LF_POLY_EVEN);
  370. for(o = o_head; o <= o_tail; ++o, ++s) {
  371. struct Crypto1State temp = {0, 0};
  372. temp.even = odd[o];
  373. temp.odd = even[e] ^ evenparity32(odd[o] & LF_POLY_ODD);
  374. if(check_state(&temp, p)) {
  375. return -1;
  376. }
  377. }
  378. }
  379. return s;
  380. }
  381. if(first_run == 0) {
  382. for(i = 0; (i < 4) && (rem-- != 0); i++) {
  383. oks >>= 1;
  384. eks >>= 1;
  385. o_tail = extend_table(
  386. odd, o_head, o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1);
  387. if(o_head > o_tail) return s;
  388. e_tail =
  389. extend_table(even, e_head, e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1);
  390. if(e_head > e_tail) return s;
  391. }
  392. }
  393. first_run = 0;
  394. quicksort(odd, o_head, o_tail);
  395. quicksort(even, e_head, e_tail);
  396. while(o_tail >= o_head && e_tail >= e_head) {
  397. if(((odd[o_tail] ^ even[e_tail]) >> 24) == 0) {
  398. o_tail = binsearch(odd, o_head, o = o_tail);
  399. e_tail = binsearch(even, e_head, e = e_tail);
  400. s = old_recover(odd, o_tail--, o, oks, even, e_tail--, e, eks, rem, s, p, first_run);
  401. if(s == -1) {
  402. break;
  403. }
  404. } else if((odd[o_tail] ^ 0x80000000) > (even[e_tail] ^ 0x80000000)) {
  405. o_tail = binsearch(odd, o_head, o_tail) - 1;
  406. } else {
  407. e_tail = binsearch(even, e_head, e_tail) - 1;
  408. }
  409. }
  410. return s;
  411. }
  412. static inline int sync_state(ProgramState* program_state) {
  413. int ts = furi_hal_rtc_get_timestamp();
  414. program_state->eta_round = program_state->eta_round - (ts - program_state->eta_timestamp);
  415. program_state->eta_total = program_state->eta_total - (ts - program_state->eta_timestamp);
  416. program_state->eta_timestamp = ts;
  417. if(program_state->close_thread_please) {
  418. return 1;
  419. }
  420. return 0;
  421. }
  422. int calculate_msb_tables(
  423. int oks,
  424. int eks,
  425. int msb_round,
  426. struct Crypto1Params* p,
  427. unsigned int* states_buffer,
  428. struct Msb* odd_msbs,
  429. struct Msb* even_msbs,
  430. unsigned int* temp_states_odd,
  431. unsigned int* temp_states_even,
  432. ProgramState* program_state) {
  433. //FURI_LOG_I(TAG, "MSB GO %i", msb_iter); // DEBUG
  434. unsigned int msb_head = (MSB_LIMIT * msb_round); // msb_iter ranges from 0 to (256/MSB_LIMIT)-1
  435. unsigned int msb_tail = (MSB_LIMIT * (msb_round + 1));
  436. int states_tail = 0, tail = 0;
  437. int i = 0, j = 0, semi_state = 0, found = 0;
  438. unsigned int msb = 0;
  439. // TODO: Why is this necessary?
  440. memset(odd_msbs, 0, MSB_LIMIT * sizeof(struct Msb));
  441. memset(even_msbs, 0, MSB_LIMIT * sizeof(struct Msb));
  442. for(semi_state = 1 << 20; semi_state >= 0; semi_state--) {
  443. if(semi_state % 32768 == 0) {
  444. if(sync_state(program_state) == 1) {
  445. return 0;
  446. }
  447. }
  448. if(filter(semi_state) == (oks & 1)) { //-V547
  449. states_buffer[0] = semi_state;
  450. states_tail = state_loop(states_buffer, oks, CONST_M1_1, CONST_M2_1);
  451. for(i = states_tail; i >= 0; i--) {
  452. msb = states_buffer[i] >> 24;
  453. if((msb >= msb_head) && (msb < msb_tail)) {
  454. found = 0;
  455. for(j = 0; j < odd_msbs[msb - msb_head].tail - 1; j++) {
  456. if(odd_msbs[msb - msb_head].states[j] == states_buffer[i]) {
  457. found = 1;
  458. break;
  459. }
  460. }
  461. if(!found) {
  462. tail = odd_msbs[msb - msb_head].tail++;
  463. odd_msbs[msb - msb_head].states[tail] = states_buffer[i];
  464. }
  465. }
  466. }
  467. }
  468. if(filter(semi_state) == (eks & 1)) { //-V547
  469. states_buffer[0] = semi_state;
  470. states_tail = state_loop(states_buffer, eks, CONST_M1_2, CONST_M2_2);
  471. for(i = 0; i <= states_tail; i++) {
  472. msb = states_buffer[i] >> 24;
  473. if((msb >= msb_head) && (msb < msb_tail)) {
  474. found = 0;
  475. for(j = 0; j < even_msbs[msb - msb_head].tail; j++) {
  476. if(even_msbs[msb - msb_head].states[j] == states_buffer[i]) {
  477. found = 1;
  478. break;
  479. }
  480. }
  481. if(!found) {
  482. tail = even_msbs[msb - msb_head].tail++;
  483. even_msbs[msb - msb_head].states[tail] = states_buffer[i];
  484. }
  485. }
  486. }
  487. }
  488. }
  489. oks >>= 12;
  490. eks >>= 12;
  491. for(i = 0; i < MSB_LIMIT; i++) {
  492. if(sync_state(program_state) == 1) {
  493. return 0;
  494. }
  495. // TODO: Why is this necessary?
  496. memset(temp_states_even, 0, sizeof(unsigned int) * (1280));
  497. memset(temp_states_odd, 0, sizeof(unsigned int) * (1280));
  498. memcpy(temp_states_odd, odd_msbs[i].states, odd_msbs[i].tail * sizeof(unsigned int));
  499. memcpy(temp_states_even, even_msbs[i].states, even_msbs[i].tail * sizeof(unsigned int));
  500. int res = old_recover(
  501. temp_states_odd,
  502. 0,
  503. odd_msbs[i].tail,
  504. oks,
  505. temp_states_even,
  506. 0,
  507. even_msbs[i].tail,
  508. eks,
  509. 3,
  510. 0,
  511. p,
  512. 1);
  513. if(res == -1) {
  514. return 1;
  515. }
  516. //odd_msbs[i].tail = 0;
  517. //even_msbs[i].tail = 0;
  518. }
  519. return 0;
  520. }
  521. bool recover(struct Crypto1Params* p, int ks2, ProgramState* program_state) {
  522. bool found = false;
  523. unsigned int* states_buffer = malloc(sizeof(unsigned int) * (2 << 9));
  524. struct Msb* odd_msbs = (struct Msb*)malloc(MSB_LIMIT * sizeof(struct Msb));
  525. struct Msb* even_msbs = (struct Msb*)malloc(MSB_LIMIT * sizeof(struct Msb));
  526. unsigned int* temp_states_odd = malloc(sizeof(unsigned int) * (1280));
  527. unsigned int* temp_states_even = malloc(sizeof(unsigned int) * (1280));
  528. int oks = 0, eks = 0;
  529. int i = 0, msb = 0;
  530. for(i = 31; i >= 0; i -= 2) {
  531. oks = oks << 1 | BEBIT(ks2, i);
  532. }
  533. for(i = 30; i >= 0; i -= 2) {
  534. eks = eks << 1 | BEBIT(ks2, i);
  535. }
  536. int bench_start = furi_hal_rtc_get_timestamp();
  537. program_state->eta_total = eta_total_time;
  538. program_state->eta_timestamp = bench_start;
  539. for(msb = 0; msb <= ((256 / MSB_LIMIT) - 1); msb++) {
  540. program_state->search = msb;
  541. program_state->eta_round = eta_round_time;
  542. program_state->eta_total = eta_total_time - (eta_round_time * msb);
  543. if(calculate_msb_tables(
  544. oks,
  545. eks,
  546. msb,
  547. p,
  548. states_buffer,
  549. odd_msbs,
  550. even_msbs,
  551. temp_states_odd,
  552. temp_states_even,
  553. program_state)) {
  554. int bench_stop = furi_hal_rtc_get_timestamp();
  555. FURI_LOG_I(TAG, "Cracked in %i seconds", bench_stop - bench_start);
  556. found = true;
  557. break;
  558. }
  559. if(program_state->close_thread_please) {
  560. break;
  561. }
  562. }
  563. free(states_buffer);
  564. free(odd_msbs);
  565. free(even_msbs);
  566. free(temp_states_odd);
  567. free(temp_states_even);
  568. return found;
  569. }
  570. bool napi_mf_classic_dict_check_presence(MfClassicDictType dict_type) {
  571. Storage* storage = furi_record_open(RECORD_STORAGE);
  572. bool dict_present = false;
  573. if(dict_type == MfClassicDictTypeSystem) {
  574. dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_FLIPPER_PATH, NULL) == FSE_OK;
  575. } else if(dict_type == MfClassicDictTypeUser) {
  576. dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_USER_PATH, NULL) == FSE_OK;
  577. }
  578. furi_record_close(RECORD_STORAGE);
  579. return dict_present;
  580. }
  581. MfClassicDict* napi_mf_classic_dict_alloc(MfClassicDictType dict_type) {
  582. MfClassicDict* dict = malloc(sizeof(MfClassicDict));
  583. Storage* storage = furi_record_open(RECORD_STORAGE);
  584. dict->stream = buffered_file_stream_alloc(storage);
  585. furi_record_close(RECORD_STORAGE);
  586. bool dict_loaded = false;
  587. do {
  588. if(dict_type == MfClassicDictTypeSystem) {
  589. if(!buffered_file_stream_open(
  590. dict->stream,
  591. MF_CLASSIC_DICT_FLIPPER_PATH,
  592. FSAM_READ_WRITE,
  593. FSOM_OPEN_EXISTING)) {
  594. buffered_file_stream_close(dict->stream);
  595. break;
  596. }
  597. } else if(dict_type == MfClassicDictTypeUser) {
  598. if(!buffered_file_stream_open(
  599. dict->stream, MF_CLASSIC_DICT_USER_PATH, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) {
  600. buffered_file_stream_close(dict->stream);
  601. break;
  602. }
  603. }
  604. // Check for newline ending
  605. if(!stream_eof(dict->stream)) {
  606. if(!stream_seek(dict->stream, -1, StreamOffsetFromEnd)) break;
  607. uint8_t last_char = 0;
  608. if(stream_read(dict->stream, &last_char, 1) != 1) break;
  609. if(last_char != '\n') {
  610. FURI_LOG_D(TAG, "Adding new line ending");
  611. if(stream_write_char(dict->stream, '\n') != 1) break;
  612. }
  613. if(!stream_rewind(dict->stream)) break;
  614. }
  615. // Read total amount of keys
  616. FuriString* next_line;
  617. next_line = furi_string_alloc();
  618. while(true) {
  619. if(!stream_read_line(dict->stream, next_line)) {
  620. FURI_LOG_T(TAG, "No keys left in dict");
  621. break;
  622. }
  623. FURI_LOG_T(
  624. TAG,
  625. "Read line: %s, len: %zu",
  626. furi_string_get_cstr(next_line),
  627. furi_string_size(next_line));
  628. if(furi_string_get_char(next_line, 0) == '#') continue;
  629. if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
  630. dict->total_keys++;
  631. }
  632. furi_string_free(next_line);
  633. stream_rewind(dict->stream);
  634. dict_loaded = true;
  635. FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", dict->total_keys);
  636. } while(false);
  637. if(!dict_loaded) {
  638. buffered_file_stream_close(dict->stream);
  639. free(dict);
  640. dict = NULL;
  641. }
  642. return dict;
  643. }
  644. bool napi_mf_classic_dict_add_key_str(MfClassicDict* dict, FuriString* key) {
  645. furi_assert(dict);
  646. furi_assert(dict->stream);
  647. FURI_LOG_I(TAG, "Saving key: %s", furi_string_get_cstr(key));
  648. furi_string_cat_printf(key, "\n");
  649. bool key_added = false;
  650. do {
  651. if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break;
  652. if(!stream_insert_string(dict->stream, key)) break;
  653. dict->total_keys++;
  654. key_added = true;
  655. } while(false);
  656. furi_string_left(key, 12);
  657. return key_added;
  658. }
  659. void napi_mf_classic_dict_free(MfClassicDict* dict) {
  660. furi_assert(dict);
  661. furi_assert(dict->stream);
  662. buffered_file_stream_close(dict->stream);
  663. stream_free(dict->stream);
  664. free(dict);
  665. }
  666. static void napi_mf_classic_dict_int_to_str(uint8_t* key_int, FuriString* key_str) {
  667. furi_string_reset(key_str);
  668. for(size_t i = 0; i < 6; i++) {
  669. furi_string_cat_printf(key_str, "%02X", key_int[i]);
  670. }
  671. }
  672. static void napi_mf_classic_dict_str_to_int(FuriString* key_str, uint64_t* key_int) {
  673. uint8_t key_byte_tmp;
  674. *key_int = 0ULL;
  675. for(uint8_t i = 0; i < 12; i += 2) {
  676. args_char_to_hex(
  677. furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp);
  678. *key_int |= (uint64_t)key_byte_tmp << (8 * (5 - i / 2));
  679. }
  680. }
  681. uint32_t napi_mf_classic_dict_get_total_keys(MfClassicDict* dict) {
  682. furi_assert(dict);
  683. return dict->total_keys;
  684. }
  685. bool napi_mf_classic_dict_rewind(MfClassicDict* dict) {
  686. furi_assert(dict);
  687. furi_assert(dict->stream);
  688. return stream_rewind(dict->stream);
  689. }
  690. bool napi_mf_classic_dict_get_next_key_str(MfClassicDict* dict, FuriString* key) {
  691. furi_assert(dict);
  692. furi_assert(dict->stream);
  693. bool key_read = false;
  694. furi_string_reset(key);
  695. while(!key_read) {
  696. if(!stream_read_line(dict->stream, key)) break;
  697. if(furi_string_get_char(key, 0) == '#') continue;
  698. if(furi_string_size(key) != NFC_MF_CLASSIC_KEY_LEN) continue;
  699. furi_string_left(key, 12);
  700. key_read = true;
  701. }
  702. return key_read;
  703. }
  704. bool napi_mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) {
  705. furi_assert(dict);
  706. furi_assert(dict->stream);
  707. FuriString* temp_key;
  708. temp_key = furi_string_alloc();
  709. bool key_read = napi_mf_classic_dict_get_next_key_str(dict, temp_key);
  710. if(key_read) {
  711. napi_mf_classic_dict_str_to_int(temp_key, key);
  712. }
  713. furi_string_free(temp_key);
  714. return key_read;
  715. }
  716. bool napi_mf_classic_dict_is_key_present_str(MfClassicDict* dict, FuriString* key) {
  717. furi_assert(dict);
  718. furi_assert(dict->stream);
  719. FuriString* next_line;
  720. next_line = furi_string_alloc();
  721. bool key_found = false;
  722. stream_rewind(dict->stream);
  723. while(!key_found) { //-V654
  724. if(!stream_read_line(dict->stream, next_line)) break;
  725. if(furi_string_get_char(next_line, 0) == '#') continue;
  726. if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
  727. furi_string_left(next_line, 12);
  728. if(!furi_string_equal(key, next_line)) continue;
  729. key_found = true;
  730. }
  731. furi_string_free(next_line);
  732. return key_found;
  733. }
  734. bool napi_mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key) {
  735. FuriString* temp_key;
  736. temp_key = furi_string_alloc();
  737. napi_mf_classic_dict_int_to_str(key, temp_key);
  738. bool key_found = napi_mf_classic_dict_is_key_present_str(dict, temp_key);
  739. furi_string_free(temp_key);
  740. return key_found;
  741. }
  742. bool napi_key_already_found_for_nonce(
  743. MfClassicDict* dict,
  744. uint32_t uid_xor_nt1,
  745. uint32_t nr1_enc,
  746. uint32_t p64b,
  747. uint32_t ar1_enc) {
  748. bool found = false;
  749. uint64_t k = 0;
  750. napi_mf_classic_dict_rewind(dict);
  751. while(napi_mf_classic_dict_get_next_key(dict, &k)) {
  752. struct Crypto1State temp = {0, 0};
  753. int i;
  754. for(i = 0; i < 24; i++) {
  755. (&temp)->odd |= (BIT(k, 2 * i + 1) << (i ^ 3));
  756. (&temp)->even |= (BIT(k, 2 * i) << (i ^ 3));
  757. }
  758. crypt_word_noret(&temp, uid_xor_nt1, 0);
  759. crypt_word_noret(&temp, nr1_enc, 1);
  760. if(ar1_enc == (crypt_word(&temp) ^ p64b)) {
  761. found = true;
  762. break;
  763. }
  764. }
  765. return found;
  766. }
  767. bool napi_mf_classic_nonces_check_presence() {
  768. Storage* storage = furi_record_open(RECORD_STORAGE);
  769. bool nonces_present = storage_common_stat(storage, MF_CLASSIC_NONCE_PATH, NULL) == FSE_OK;
  770. furi_record_close(RECORD_STORAGE);
  771. return nonces_present;
  772. }
  773. MfClassicNonceArray* napi_mf_classic_nonce_array_alloc(
  774. MfClassicDict* system_dict,
  775. bool system_dict_exists,
  776. MfClassicDict* user_dict,
  777. ProgramState* program_state) {
  778. MfClassicNonceArray* nonce_array = malloc(sizeof(MfClassicNonceArray));
  779. MfClassicNonce* remaining_nonce_array_init = malloc(sizeof(MfClassicNonce) * 1);
  780. nonce_array->remaining_nonce_array = remaining_nonce_array_init;
  781. Storage* storage = furi_record_open(RECORD_STORAGE);
  782. nonce_array->stream = buffered_file_stream_alloc(storage);
  783. furi_record_close(RECORD_STORAGE);
  784. bool array_loaded = false;
  785. do {
  786. // https://github.com/flipperdevices/flipperzero-firmware/blob/5134f44c09d39344a8747655c0d59864bb574b96/applications/services/storage/filesystem_api_defines.h#L8-L22
  787. if(!buffered_file_stream_open(
  788. nonce_array->stream, MF_CLASSIC_NONCE_PATH, FSAM_READ_WRITE, FSOM_OPEN_EXISTING)) {
  789. buffered_file_stream_close(nonce_array->stream);
  790. break;
  791. }
  792. // Check for newline ending
  793. if(!stream_eof(nonce_array->stream)) {
  794. if(!stream_seek(nonce_array->stream, -1, StreamOffsetFromEnd)) break;
  795. uint8_t last_char = 0;
  796. if(stream_read(nonce_array->stream, &last_char, 1) != 1) break;
  797. if(last_char != '\n') {
  798. FURI_LOG_D(TAG, "Adding new line ending");
  799. if(stream_write_char(nonce_array->stream, '\n') != 1) break;
  800. }
  801. if(!stream_rewind(nonce_array->stream)) break;
  802. }
  803. // Read total amount of nonces
  804. FuriString* next_line;
  805. next_line = furi_string_alloc();
  806. while(!(program_state->close_thread_please)) {
  807. if(!stream_read_line(nonce_array->stream, next_line)) {
  808. FURI_LOG_T(TAG, "No nonces left");
  809. break;
  810. }
  811. FURI_LOG_T(
  812. TAG,
  813. "Read line: %s, len: %zu",
  814. furi_string_get_cstr(next_line),
  815. furi_string_size(next_line));
  816. if(!furi_string_start_with_str(next_line, "Sec")) continue;
  817. const char* next_line_cstr = furi_string_get_cstr(next_line);
  818. MfClassicNonce res = {0};
  819. int i = 0;
  820. char* endptr;
  821. for(i = 0; i <= 17; i++) {
  822. if(i != 0) {
  823. next_line_cstr = strchr(next_line_cstr, ' ');
  824. if(next_line_cstr) {
  825. next_line_cstr++;
  826. } else {
  827. break;
  828. }
  829. }
  830. unsigned long value = strtoul(next_line_cstr, &endptr, 16);
  831. switch(i) {
  832. case 5:
  833. res.uid = value;
  834. break;
  835. case 7:
  836. res.nt0 = value;
  837. break;
  838. case 9:
  839. res.nr0_enc = value;
  840. break;
  841. case 11:
  842. res.ar0_enc = value;
  843. break;
  844. case 13:
  845. res.nt1 = value;
  846. break;
  847. case 15:
  848. res.nr1_enc = value;
  849. break;
  850. case 17:
  851. res.ar1_enc = value;
  852. break;
  853. default:
  854. break; // Do nothing
  855. }
  856. next_line_cstr = endptr;
  857. }
  858. (program_state->total)++;
  859. uint32_t p64b = prng_successor(res.nt1, 64);
  860. if((system_dict_exists &&
  861. napi_key_already_found_for_nonce(
  862. system_dict, res.uid ^ res.nt1, res.nr1_enc, p64b, res.ar1_enc)) ||
  863. (napi_key_already_found_for_nonce(
  864. user_dict, res.uid ^ res.nt1, res.nr1_enc, p64b, res.ar1_enc))) {
  865. (program_state->cracked)++;
  866. (program_state->num_completed)++;
  867. continue;
  868. }
  869. FURI_LOG_I(TAG, "No key found for %8lx %8lx", res.uid, res.ar1_enc);
  870. // TODO: Refactor
  871. nonce_array->remaining_nonce_array = realloc( //-V701
  872. nonce_array->remaining_nonce_array,
  873. sizeof(MfClassicNonce) * ((nonce_array->remaining_nonces) + 1));
  874. nonce_array->remaining_nonces++;
  875. nonce_array->remaining_nonce_array[(nonce_array->remaining_nonces) - 1] = res;
  876. nonce_array->total_nonces++;
  877. }
  878. furi_string_free(next_line);
  879. buffered_file_stream_close(nonce_array->stream);
  880. array_loaded = true;
  881. FURI_LOG_I(TAG, "Loaded %lu nonces", nonce_array->total_nonces);
  882. } while(false);
  883. if(!array_loaded) {
  884. free(nonce_array);
  885. nonce_array = NULL;
  886. }
  887. return nonce_array;
  888. }
  889. void napi_mf_classic_nonce_array_free(MfClassicNonceArray* nonce_array) {
  890. furi_assert(nonce_array);
  891. furi_assert(nonce_array->stream);
  892. buffered_file_stream_close(nonce_array->stream);
  893. stream_free(nonce_array->stream);
  894. free(nonce_array);
  895. }
  896. static void finished_beep() {
  897. // Beep to indicate completion
  898. NotificationApp* notification = furi_record_open("notification");
  899. notification_message(notification, &sequence_audiovisual_alert);
  900. notification_message(notification, &sequence_display_backlight_on);
  901. furi_record_close("notification");
  902. }
  903. void mfkey32(ProgramState* program_state) {
  904. uint64_t found_key; // recovered key
  905. size_t keyarray_size = 0;
  906. uint64_t* keyarray = malloc(sizeof(uint64_t) * 1);
  907. uint32_t i = 0, j = 0;
  908. // Check for nonces
  909. if(!napi_mf_classic_nonces_check_presence()) {
  910. program_state->err = MissingNonces;
  911. program_state->mfkey_state = Error;
  912. free(keyarray);
  913. return;
  914. }
  915. // Read dictionaries (optional)
  916. MfClassicDict* system_dict = {0};
  917. bool system_dict_exists = napi_mf_classic_dict_check_presence(MfClassicDictTypeSystem);
  918. MfClassicDict* user_dict = {0};
  919. bool user_dict_exists = napi_mf_classic_dict_check_presence(MfClassicDictTypeUser);
  920. uint32_t total_dict_keys = 0;
  921. if(system_dict_exists) {
  922. system_dict = napi_mf_classic_dict_alloc(MfClassicDictTypeSystem);
  923. total_dict_keys += napi_mf_classic_dict_get_total_keys(system_dict);
  924. }
  925. user_dict = napi_mf_classic_dict_alloc(MfClassicDictTypeUser);
  926. if(user_dict_exists) {
  927. total_dict_keys += napi_mf_classic_dict_get_total_keys(user_dict);
  928. }
  929. user_dict_exists = true;
  930. program_state->dict_count = total_dict_keys;
  931. program_state->mfkey_state = DictionaryAttack;
  932. // Read nonces
  933. MfClassicNonceArray* nonce_arr;
  934. nonce_arr = napi_mf_classic_nonce_array_alloc(
  935. system_dict, system_dict_exists, user_dict, program_state);
  936. if(system_dict_exists) {
  937. napi_mf_classic_dict_free(system_dict);
  938. }
  939. if(nonce_arr->total_nonces == 0) {
  940. // Nothing to crack
  941. program_state->err = ZeroNonces;
  942. program_state->mfkey_state = Error;
  943. napi_mf_classic_nonce_array_free(nonce_arr);
  944. napi_mf_classic_dict_free(user_dict);
  945. free(keyarray);
  946. return;
  947. }
  948. if(memmgr_get_free_heap() < MIN_RAM) {
  949. // System has less than the guaranteed amount of RAM (140 KB) - adjust some parameters to run anyway at half speed
  950. eta_round_time *= 2;
  951. eta_total_time *= 2;
  952. MSB_LIMIT /= 2;
  953. }
  954. program_state->mfkey_state = MfkeyAttack;
  955. // TODO: Work backwards on this array and free memory
  956. for(i = 0; i < nonce_arr->total_nonces; i++) {
  957. MfClassicNonce next_nonce = nonce_arr->remaining_nonce_array[i];
  958. uint32_t p64 = prng_successor(next_nonce.nt0, 64);
  959. uint32_t p64b = prng_successor(next_nonce.nt1, 64);
  960. if(key_already_found_for_nonce(
  961. keyarray,
  962. keyarray_size,
  963. next_nonce.uid ^ next_nonce.nt1,
  964. next_nonce.nr1_enc,
  965. p64b,
  966. next_nonce.ar1_enc)) {
  967. nonce_arr->remaining_nonces--;
  968. (program_state->cracked)++;
  969. (program_state->num_completed)++;
  970. continue;
  971. }
  972. FURI_LOG_I(TAG, "Cracking %8lx %8lx", next_nonce.uid, next_nonce.ar1_enc);
  973. struct Crypto1Params p = {
  974. 0,
  975. next_nonce.nr0_enc,
  976. next_nonce.uid ^ next_nonce.nt0,
  977. next_nonce.uid ^ next_nonce.nt1,
  978. next_nonce.nr1_enc,
  979. p64b,
  980. next_nonce.ar1_enc};
  981. if(!recover(&p, next_nonce.ar0_enc ^ p64, program_state)) {
  982. if(program_state->close_thread_please) {
  983. break;
  984. }
  985. // No key found in recover()
  986. (program_state->num_completed)++;
  987. continue;
  988. }
  989. (program_state->cracked)++;
  990. (program_state->num_completed)++;
  991. found_key = p.key;
  992. bool already_found = false;
  993. for(j = 0; j < keyarray_size; j++) {
  994. if(keyarray[j] == found_key) {
  995. already_found = true;
  996. break;
  997. }
  998. }
  999. if(already_found == false) {
  1000. // New key
  1001. keyarray = realloc(keyarray, sizeof(uint64_t) * (keyarray_size + 1)); //-V701
  1002. keyarray_size += 1;
  1003. keyarray[keyarray_size - 1] = found_key;
  1004. (program_state->unique_cracked)++;
  1005. }
  1006. }
  1007. // TODO: Update display to show all keys were found
  1008. // TODO: Prepend found key(s) to user dictionary file
  1009. //FURI_LOG_I(TAG, "Unique keys found:");
  1010. for(i = 0; i < keyarray_size; i++) {
  1011. //FURI_LOG_I(TAG, "%012" PRIx64, keyarray[i]);
  1012. FuriString* temp_key = furi_string_alloc();
  1013. furi_string_cat_printf(temp_key, "%012" PRIX64, keyarray[i]);
  1014. napi_mf_classic_dict_add_key_str(user_dict, temp_key);
  1015. furi_string_free(temp_key);
  1016. }
  1017. if(keyarray_size > 0) {
  1018. // TODO: Should we use DolphinDeedNfcMfcAdd?
  1019. dolphin_deed(DolphinDeedNfcMfcAdd);
  1020. }
  1021. napi_mf_classic_nonce_array_free(nonce_arr);
  1022. napi_mf_classic_dict_free(user_dict);
  1023. free(keyarray);
  1024. //FURI_LOG_I(TAG, "mfkey32 function completed normally"); // DEBUG
  1025. program_state->mfkey_state = Complete;
  1026. // No need to alert the user if they asked it to stop
  1027. if(!(program_state->close_thread_please)) {
  1028. finished_beep();
  1029. }
  1030. return;
  1031. }
  1032. // Screen is 128x64 px
  1033. static void render_callback(Canvas* const canvas, void* ctx) {
  1034. furi_assert(ctx);
  1035. ProgramState* program_state = ctx;
  1036. furi_mutex_acquire(program_state->mutex, FuriWaitForever);
  1037. char draw_str[44] = {};
  1038. canvas_clear(canvas);
  1039. canvas_draw_frame(canvas, 0, 0, 128, 64);
  1040. canvas_draw_frame(canvas, 0, 15, 128, 64);
  1041. canvas_set_font(canvas, FontPrimary);
  1042. canvas_draw_str_aligned(canvas, 5, 4, AlignLeft, AlignTop, "Mfkey32");
  1043. canvas_draw_icon(canvas, 114, 4, &I_mfkey);
  1044. if(program_state->is_thread_running && program_state->mfkey_state == MfkeyAttack) {
  1045. float eta_round = (float)1 - ((float)program_state->eta_round / (float)eta_round_time);
  1046. float eta_total = (float)1 - ((float)program_state->eta_total / (float)eta_total_time);
  1047. float progress = (float)program_state->num_completed / (float)program_state->total;
  1048. if(eta_round < 0) {
  1049. // Round ETA miscalculated
  1050. eta_round = 1;
  1051. program_state->eta_round = 0;
  1052. }
  1053. if(eta_total < 0) {
  1054. // Total ETA miscalculated
  1055. eta_total = 1;
  1056. program_state->eta_total = 0;
  1057. }
  1058. canvas_set_font(canvas, FontSecondary);
  1059. snprintf(
  1060. draw_str,
  1061. sizeof(draw_str),
  1062. "Cracking: %d/%d - in prog.",
  1063. program_state->num_completed,
  1064. program_state->total);
  1065. elements_progress_bar_with_text(canvas, 5, 18, 118, progress, draw_str);
  1066. snprintf(
  1067. draw_str,
  1068. sizeof(draw_str),
  1069. "Round: %d/%d - ETA %02d Sec",
  1070. (program_state->search) + 1, // Zero indexed
  1071. 256 / MSB_LIMIT,
  1072. program_state->eta_round);
  1073. elements_progress_bar_with_text(canvas, 5, 31, 118, eta_round, draw_str);
  1074. snprintf(draw_str, sizeof(draw_str), "Total ETA %03d Sec", program_state->eta_total);
  1075. elements_progress_bar_with_text(canvas, 5, 44, 118, eta_total, draw_str);
  1076. } else if(program_state->is_thread_running && program_state->mfkey_state == DictionaryAttack) {
  1077. canvas_set_font(canvas, FontSecondary);
  1078. snprintf(
  1079. draw_str, sizeof(draw_str), "Dict solves: %d (in progress)", program_state->cracked);
  1080. canvas_draw_str_aligned(canvas, 10, 18, AlignLeft, AlignTop, draw_str);
  1081. snprintf(draw_str, sizeof(draw_str), "Keys in dict: %d", program_state->dict_count);
  1082. canvas_draw_str_aligned(canvas, 26, 28, AlignLeft, AlignTop, draw_str);
  1083. } else if(program_state->mfkey_state == Complete) {
  1084. // TODO: Scrollable list view to see cracked keys if user presses down
  1085. elements_progress_bar_with_text(canvas, 5, 18, 118, 1, draw_str);
  1086. canvas_set_font(canvas, FontSecondary);
  1087. snprintf(draw_str, sizeof(draw_str), "Complete");
  1088. canvas_draw_str_aligned(canvas, 40, 31, AlignLeft, AlignTop, draw_str);
  1089. snprintf(
  1090. draw_str,
  1091. sizeof(draw_str),
  1092. "Keys added to user dict: %d",
  1093. program_state->unique_cracked);
  1094. canvas_draw_str_aligned(canvas, 10, 41, AlignLeft, AlignTop, draw_str);
  1095. } else if(program_state->mfkey_state == Ready) {
  1096. canvas_set_font(canvas, FontSecondary);
  1097. canvas_draw_str_aligned(canvas, 50, 30, AlignLeft, AlignTop, "Ready");
  1098. elements_button_center(canvas, "Start");
  1099. elements_button_right(canvas, "Help");
  1100. } else if(program_state->mfkey_state == Help) {
  1101. canvas_set_font(canvas, FontSecondary);
  1102. canvas_draw_str_aligned(canvas, 7, 20, AlignLeft, AlignTop, "Collect nonces using");
  1103. canvas_draw_str_aligned(canvas, 7, 30, AlignLeft, AlignTop, "Detect Reader.");
  1104. canvas_draw_str_aligned(canvas, 7, 40, AlignLeft, AlignTop, "Developers: noproto, AG");
  1105. canvas_draw_str_aligned(canvas, 7, 50, AlignLeft, AlignTop, "Thanks: bettse");
  1106. } else if(program_state->mfkey_state == Error) {
  1107. canvas_draw_str_aligned(canvas, 50, 25, AlignLeft, AlignTop, "Error");
  1108. canvas_set_font(canvas, FontSecondary);
  1109. if(program_state->err == MissingNonces) {
  1110. canvas_draw_str_aligned(canvas, 25, 36, AlignLeft, AlignTop, "No nonces found");
  1111. } else if(program_state->err == ZeroNonces) {
  1112. canvas_draw_str_aligned(canvas, 15, 36, AlignLeft, AlignTop, "Nonces already cracked");
  1113. } else {
  1114. // Unhandled error
  1115. }
  1116. } else {
  1117. // Unhandled program state
  1118. }
  1119. furi_mutex_release(program_state->mutex);
  1120. }
  1121. static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
  1122. furi_assert(event_queue);
  1123. PluginEvent event = {.type = EventTypeKey, .input = *input_event};
  1124. furi_message_queue_put(event_queue, &event, FuriWaitForever);
  1125. }
  1126. static void mfkey32_state_init(ProgramState* program_state) {
  1127. program_state->is_thread_running = false;
  1128. program_state->mfkey_state = Ready;
  1129. program_state->cracked = 0;
  1130. program_state->unique_cracked = 0;
  1131. program_state->num_completed = 0;
  1132. program_state->total = 0;
  1133. program_state->dict_count = 0;
  1134. }
  1135. // Entrypoint for worker thread
  1136. static int32_t mfkey32_worker_thread(void* ctx) {
  1137. ProgramState* program_state = ctx;
  1138. program_state->is_thread_running = true;
  1139. program_state->mfkey_state = Initializing;
  1140. //FURI_LOG_I(TAG, "Hello from the mfkey32 worker thread"); // DEBUG
  1141. mfkey32(program_state);
  1142. program_state->is_thread_running = false;
  1143. return 0;
  1144. }
  1145. void start_mfkey32_thread(ProgramState* program_state) {
  1146. if(!program_state->is_thread_running) {
  1147. furi_thread_start(program_state->mfkeythread);
  1148. }
  1149. }
  1150. int32_t mfkey32_main() {
  1151. FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
  1152. ProgramState* program_state = malloc(sizeof(ProgramState));
  1153. mfkey32_state_init(program_state);
  1154. program_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  1155. if(!program_state->mutex) {
  1156. FURI_LOG_E(TAG, "cannot create mutex\r\n");
  1157. free(program_state);
  1158. return 255;
  1159. }
  1160. // Set system callbacks
  1161. ViewPort* view_port = view_port_alloc();
  1162. view_port_draw_callback_set(view_port, render_callback, program_state);
  1163. view_port_input_callback_set(view_port, input_callback, event_queue);
  1164. // Open GUI and register view_port
  1165. Gui* gui = furi_record_open(RECORD_GUI);
  1166. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  1167. program_state->mfkeythread = furi_thread_alloc();
  1168. furi_thread_set_name(program_state->mfkeythread, "Mfkey32 Worker");
  1169. furi_thread_set_stack_size(program_state->mfkeythread, 2048);
  1170. furi_thread_set_context(program_state->mfkeythread, program_state);
  1171. furi_thread_set_callback(program_state->mfkeythread, mfkey32_worker_thread);
  1172. PluginEvent event;
  1173. for(bool main_loop = true; main_loop;) {
  1174. FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
  1175. furi_mutex_acquire(program_state->mutex, FuriWaitForever);
  1176. if(event_status == FuriStatusOk) {
  1177. // press events
  1178. if(event.type == EventTypeKey) {
  1179. if(event.input.type == InputTypePress) {
  1180. switch(event.input.key) {
  1181. case InputKeyUp:
  1182. break;
  1183. case InputKeyDown:
  1184. break;
  1185. case InputKeyRight:
  1186. if(!program_state->is_thread_running &&
  1187. program_state->mfkey_state == Ready) {
  1188. program_state->mfkey_state = Help;
  1189. view_port_update(view_port);
  1190. }
  1191. break;
  1192. case InputKeyLeft:
  1193. break;
  1194. case InputKeyOk:
  1195. if(!program_state->is_thread_running &&
  1196. program_state->mfkey_state == Ready) {
  1197. start_mfkey32_thread(program_state);
  1198. view_port_update(view_port);
  1199. }
  1200. break;
  1201. case InputKeyBack:
  1202. if(!program_state->is_thread_running &&
  1203. program_state->mfkey_state == Help) {
  1204. program_state->mfkey_state = Ready;
  1205. view_port_update(view_port);
  1206. } else {
  1207. program_state->close_thread_please = true;
  1208. if(program_state->is_thread_running && program_state->mfkeythread) {
  1209. // Wait until thread is finished
  1210. furi_thread_join(program_state->mfkeythread);
  1211. }
  1212. program_state->close_thread_please = false;
  1213. main_loop = false;
  1214. }
  1215. break;
  1216. default:
  1217. break;
  1218. }
  1219. }
  1220. }
  1221. }
  1222. furi_mutex_release(program_state->mutex);
  1223. view_port_update(view_port);
  1224. }
  1225. furi_thread_free(program_state->mfkeythread);
  1226. view_port_enabled_set(view_port, false);
  1227. gui_remove_view_port(gui, view_port);
  1228. furi_record_close("gui");
  1229. view_port_free(view_port);
  1230. furi_message_queue_free(event_queue);
  1231. furi_mutex_free(program_state->mutex);
  1232. free(program_state);
  1233. return 0;
  1234. }