gen4.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "gen4.h"
  2. #include <furi_hal_nfc.h>
  3. #include <stdlib.h>
  4. #define TAG "Magic"
  5. #define MAGIC_CMD_PREFIX (0xCF)
  6. #define MAGIC_CMD_GET_CFG (0xC6)
  7. #define MAGIC_CMD_WRITE (0xCD)
  8. #define MAGIC_CMD_READ (0xCE)
  9. #define MAGIC_CMD_SET_CFG (0xF0)
  10. #define MAGIC_CMD_FUSE_CFG (0xF1)
  11. #define MAGIC_CMD_SET_PWD (0xFE)
  12. #define MAGIC_BUFFER_SIZE (40)
  13. const uint8_t MAGIC_DEFAULT_CONFIG[] = {
  14. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x00, 0x08, 0x00, 0x6b, 0x02
  15. };
  16. const uint8_t MAGIC_DEFAULT_BLOCK0[] = {
  17. 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  18. };
  19. const uint8_t MAGIC_EMPTY_BLOCK[16] = { 0 };
  20. const uint8_t MAGIC_DEFAULT_SECTOR_TRAILER[] = {
  21. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  22. };
  23. static bool magic_gen4_is_block_num_trailer(uint8_t n) {
  24. n++;
  25. if (n < 32 * 4) {
  26. return (n % 4 == 0);
  27. }
  28. return (n % 16 == 0);
  29. }
  30. bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config) {
  31. bool is_valid_config_len = false;
  32. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  33. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  34. uint16_t rx_len = 0;
  35. FuriHalNfcReturn ret = 0;
  36. do {
  37. // Start communication
  38. tx_data[0] = MAGIC_CMD_PREFIX;
  39. tx_data[1] = (uint8_t)(pwd >> 24);
  40. tx_data[2] = (uint8_t)(pwd >> 16);
  41. tx_data[3] = (uint8_t)(pwd >> 8);
  42. tx_data[4] = (uint8_t)pwd;
  43. tx_data[5] = MAGIC_CMD_GET_CFG;
  44. ret = furi_hal_nfc_ll_txrx(
  45. tx_data,
  46. 6,
  47. rx_data,
  48. sizeof(rx_data),
  49. &rx_len,
  50. FURI_HAL_NFC_TXRX_DEFAULT,
  51. furi_hal_nfc_ll_ms2fc(20));
  52. if(ret != FuriHalNfcReturnOk) break;
  53. if(rx_len != 30 && rx_len != 32) break;
  54. memcpy(config, rx_data, rx_len);
  55. is_valid_config_len = true;
  56. } while(false);
  57. return is_valid_config_len;
  58. }
  59. bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse) {
  60. bool write_success = false;
  61. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  62. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  63. uint16_t rx_len = 0;
  64. FuriHalNfcReturn ret = 0;
  65. do {
  66. // Start communication
  67. tx_data[0] = MAGIC_CMD_PREFIX;
  68. tx_data[1] = (uint8_t)(pwd >> 24);
  69. tx_data[2] = (uint8_t)(pwd >> 16);
  70. tx_data[3] = (uint8_t)(pwd >> 8);
  71. tx_data[4] = (uint8_t)pwd;
  72. tx_data[5] = fuse ? MAGIC_CMD_FUSE_CFG : MAGIC_CMD_SET_CFG;
  73. memcpy(tx_data + 6, config, config_length);
  74. ret = furi_hal_nfc_ll_txrx(
  75. tx_data,
  76. 6 + config_length,
  77. rx_data,
  78. sizeof(rx_data),
  79. &rx_len,
  80. FURI_HAL_NFC_TXRX_DEFAULT,
  81. furi_hal_nfc_ll_ms2fc(20));
  82. if(ret != FuriHalNfcReturnOk) break;
  83. if(rx_len != 2) break;
  84. write_success = true;
  85. } while(false);
  86. return write_success;
  87. }
  88. bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd) {
  89. bool change_success = false;
  90. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  91. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  92. uint16_t rx_len = 0;
  93. FuriHalNfcReturn ret = 0;
  94. do {
  95. // Start communication
  96. tx_data[0] = MAGIC_CMD_PREFIX;
  97. tx_data[1] = (uint8_t)(old_pwd >> 24);
  98. tx_data[2] = (uint8_t)(old_pwd >> 16);
  99. tx_data[3] = (uint8_t)(old_pwd >> 8);
  100. tx_data[4] = (uint8_t)old_pwd;
  101. tx_data[5] = MAGIC_CMD_SET_PWD;
  102. tx_data[6] = (uint8_t)(new_pwd >> 24);
  103. tx_data[7] = (uint8_t)(new_pwd >> 16);
  104. tx_data[8] = (uint8_t)(new_pwd >> 8);
  105. tx_data[9] = (uint8_t)new_pwd;
  106. ret = furi_hal_nfc_ll_txrx(
  107. tx_data,
  108. 10,
  109. rx_data,
  110. sizeof(rx_data),
  111. &rx_len,
  112. FURI_HAL_NFC_TXRX_DEFAULT,
  113. furi_hal_nfc_ll_ms2fc(20));
  114. FURI_LOG_I(TAG, "ret %d, len %d", ret, rx_len);
  115. if(ret != FuriHalNfcReturnOk) break;
  116. if(rx_len != 2) break;
  117. change_success = true;
  118. } while(false);
  119. return change_success;
  120. }
  121. bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data) {
  122. bool write_success = false;
  123. uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
  124. uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
  125. uint16_t rx_len = 0;
  126. FuriHalNfcReturn ret = 0;
  127. do {
  128. // Start communication
  129. tx_data[0] = MAGIC_CMD_PREFIX;
  130. tx_data[1] = (uint8_t)(pwd >> 24);
  131. tx_data[2] = (uint8_t)(pwd >> 16);
  132. tx_data[3] = (uint8_t)(pwd >> 8);
  133. tx_data[4] = (uint8_t)pwd;
  134. tx_data[5] = MAGIC_CMD_WRITE;
  135. tx_data[6] = block_num;
  136. memcpy(tx_data + 7, data, 16);
  137. ret = furi_hal_nfc_ll_txrx(
  138. tx_data,
  139. 23,
  140. rx_data,
  141. sizeof(rx_data),
  142. &rx_len,
  143. FURI_HAL_NFC_TXRX_DEFAULT,
  144. furi_hal_nfc_ll_ms2fc(200));
  145. if(ret != FuriHalNfcReturnOk) break;
  146. if(rx_len != 2) break;
  147. write_success = true;
  148. } while(false);
  149. return write_success;
  150. }
  151. bool magic_gen4_wipe(uint32_t pwd) {
  152. if(!magic_gen4_set_cfg(pwd, MAGIC_DEFAULT_CONFIG, sizeof(MAGIC_DEFAULT_CONFIG), false)) {
  153. FURI_LOG_E(TAG, "Set config failed");
  154. return false;
  155. }
  156. if(!magic_gen4_write_blk(pwd, 0, MAGIC_DEFAULT_BLOCK0)) {
  157. FURI_LOG_E(TAG, "Block 0 write failed");
  158. return false;
  159. }
  160. for(size_t i = 1; i < 64; i++) {
  161. const uint8_t* block = magic_gen4_is_block_num_trailer(i) ? MAGIC_DEFAULT_SECTOR_TRAILER : MAGIC_EMPTY_BLOCK;
  162. if(!magic_gen4_write_blk(pwd, i, block)) {
  163. FURI_LOG_E(TAG, "Block %d write failed", i);
  164. return false;
  165. }
  166. }
  167. for(size_t i = 65; i < 256; i++) {
  168. if(!magic_gen4_write_blk(pwd, i, MAGIC_EMPTY_BLOCK)) {
  169. FURI_LOG_E(TAG, "Block %d write failed", i);
  170. return false;
  171. }
  172. }
  173. return true;
  174. }