weebo_scene_write.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "../weebo_i.h"
  2. #include <nfc/protocols/mf_ultralight/mf_ultralight_poller.h>
  3. #define TAG "SceneWrite"
  4. static uint8_t SLB[] = {0x00, 0x00, 0x0F, 0xE0};
  5. static uint8_t CC[] = {0xf1, 0x10, 0xff, 0xee};
  6. static uint8_t DLB[] = {0x01, 0x00, 0x0f, 0xbd};
  7. static uint8_t CFG0[] = {0x00, 0x00, 0x00, 0x04};
  8. static uint8_t CFG1[] = {0x5f, 0x00, 0x00, 0x00};
  9. static uint8_t PACKRFUI[] = {0x80, 0x80, 0x00, 0x00};
  10. enum NTAG215Pages {
  11. staticLockBits = 2,
  12. capabilityContainer = 3,
  13. userMemoryFirst = 4,
  14. userMemoryLast = 129,
  15. dynamicLockBits = 130,
  16. cfg0 = 131,
  17. cfg1 = 132,
  18. pwd = 133,
  19. pack = 134,
  20. total = 135
  21. };
  22. void weebo_scene_write_calculate_pwd(uint8_t* uid, uint8_t* pwd) {
  23. pwd[0] = uid[1] ^ uid[3] ^ 0xAA;
  24. pwd[1] = uid[2] ^ uid[4] ^ 0x55;
  25. pwd[2] = uid[3] ^ uid[5] ^ 0xAA;
  26. pwd[3] = uid[4] ^ uid[6] ^ 0x55;
  27. }
  28. NfcCommand weebo_scene_write_poller_callback(NfcGenericEvent event, void* context) {
  29. furi_assert(event.protocol == NfcProtocolMfUltralight);
  30. Weebo* weebo = context;
  31. NfcCommand ret = NfcCommandContinue;
  32. const MfUltralightPollerEvent* mf_ultralight_event = event.event_data;
  33. if(mf_ultralight_event->type == MfUltralightPollerEventTypeRequestMode) {
  34. // This is called after the successful read, so we don't need to do anything special
  35. mf_ultralight_event->data->poller_mode = MfUltralightPollerModeWrite;
  36. } else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthRequest) {
  37. mf_ultralight_event->data->auth_context.skip_auth = true;
  38. } else if(mf_ultralight_event->type == MfUltralightPollerEventTypeReadSuccess) {
  39. nfc_device_set_data(
  40. weebo->nfc_device, NfcProtocolMfUltralight, nfc_poller_get_data(weebo->poller));
  41. const MfUltralightData* data =
  42. nfc_device_get_data(weebo->nfc_device, NfcProtocolMfUltralight);
  43. if(!mf_ultralight_is_all_data_read(data)) {
  44. view_dispatcher_send_custom_event(weebo->view_dispatcher, WeeboCustomEventWrongCard);
  45. ret = NfcCommandStop;
  46. return ret;
  47. }
  48. if(data->type != MfUltralightTypeNTAG215) {
  49. view_dispatcher_send_custom_event(weebo->view_dispatcher, WeeboCustomEventWrongCard);
  50. ret = NfcCommandStop;
  51. return ret;
  52. }
  53. view_dispatcher_send_custom_event(weebo->view_dispatcher, WeeboCustomEventCardDetected);
  54. FURI_LOG_D(
  55. TAG,
  56. "UID: %02X%02X%02X%02X%02X%02X",
  57. data->iso14443_3a_data->uid[0],
  58. data->iso14443_3a_data->uid[1],
  59. data->iso14443_3a_data->uid[2],
  60. data->iso14443_3a_data->uid[3],
  61. data->iso14443_3a_data->uid[4],
  62. data->iso14443_3a_data->uid[5]);
  63. for(size_t p = 0; p < 2; p++) {
  64. for(size_t i = 0; i < MF_ULTRALIGHT_PAGE_SIZE; i++) {
  65. weebo->figure[NFC3D_UID_OFFSET + p * MF_ULTRALIGHT_PAGE_SIZE + i] =
  66. data->page[p].data[i];
  67. }
  68. }
  69. uint8_t modified[NTAG215_SIZE];
  70. nfc3d_amiibo_pack(&weebo->amiiboKeys, weebo->figure, modified);
  71. FURI_LOG_D(TAG, "Re-packed");
  72. /*
  73. MfUltralightAuth* mf_ul_auth;
  74. mf_ul_auth = mf_ultralight_auth_alloc();
  75. mf_ultralight_generate_amiibo_pass(
  76. mf_ul_auth, data->iso14443_3a_data->uid, data->iso14443_3a_data->uid_len);
  77. */
  78. uint8_t PWD[4];
  79. weebo_scene_write_calculate_pwd(data->iso14443_3a_data->uid, PWD);
  80. FURI_LOG_D(TAG, "PWD: %02X%02X%02X%02X", PWD[0], PWD[1], PWD[2], PWD[3]);
  81. MfUltralightData* newdata = mf_ultralight_alloc();
  82. nfc_device_copy_data(weebo->nfc_device, NfcProtocolMfUltralight, newdata);
  83. // If I were writing these by hand, I'd order them to do the least damage first so they can be re-run
  84. // user data
  85. for(size_t i = userMemoryFirst; i <= userMemoryLast; i++) {
  86. newdata->page[i / MF_ULTRALIGHT_PAGE_SIZE].data[i % MF_ULTRALIGHT_PAGE_SIZE] =
  87. modified[i];
  88. }
  89. UNUSED(PWD);
  90. UNUSED(PACKRFUI);
  91. UNUSED(CC);
  92. UNUSED(CFG0);
  93. UNUSED(CFG1);
  94. UNUSED(DLB);
  95. UNUSED(SLB);
  96. /*
  97. // pwd
  98. memcpy(newdata->page[pwd].data, PWD, sizeof(PWD));
  99. // pack
  100. memcpy(newdata->page[pack].data, PACKRFUI, sizeof(PACKRFUI));
  101. // capability container
  102. memcpy(newdata->page[capabilityContainer].data, CC, sizeof(CC));
  103. // cfg0
  104. memcpy(newdata->page[cfg0].data, CFG0, sizeof(CFG0));
  105. // cfg1
  106. memcpy(newdata->page[cfg1].data, CFG1, sizeof(CFG1));
  107. // dynamic lock bits
  108. memcpy(newdata->page[dynamicLockBits].data, DLB, sizeof(DLB));
  109. // static lock bits
  110. memcpy(newdata->page[staticLockBits].data, SLB, sizeof(SLB));
  111. */
  112. nfc_device_set_data(weebo->nfc_device, NfcProtocolMfUltralight, newdata);
  113. mf_ultralight_free(newdata);
  114. //mf_ultralight_auth_free(weebo->mf_ul_auth);
  115. } else if(mf_ultralight_event->type == MfUltralightPollerEventTypeRequestWriteData) {
  116. // NOTE: Consider saving the first 2 pages of the data (UID + BCC) and then doing all the calculations and setting up the data in this block.
  117. mf_ultralight_event->data->write_data =
  118. nfc_device_get_data(weebo->nfc_device, NfcProtocolMfUltralight);
  119. } else if(mf_ultralight_event->type == MfUltralightPollerEventTypeWriteSuccess) {
  120. view_dispatcher_send_custom_event(weebo->view_dispatcher, WeeboCustomEventWriteSuccess);
  121. ret = NfcCommandStop;
  122. } else if(mf_ultralight_event->type == MfUltralightPollerEventTypeWriteFail) {
  123. ret = NfcCommandStop;
  124. } else {
  125. FURI_LOG_D(TAG, "Unhandled event type: %d", mf_ultralight_event->type);
  126. }
  127. return ret;
  128. }
  129. void weebo_scene_write_on_enter(void* context) {
  130. Weebo* weebo = context;
  131. Popup* popup = weebo->popup;
  132. popup_set_header(popup, "Present NTAG215", 58, 28, AlignCenter, AlignCenter);
  133. //popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
  134. // popup_set_text(popup, "words", 64, 36, AlignCenter, AlignTop);
  135. weebo->poller = nfc_poller_alloc(weebo->nfc, NfcProtocolMfUltralight);
  136. nfc_poller_start(weebo->poller, weebo_scene_write_poller_callback, weebo);
  137. weebo_blink_start(weebo);
  138. view_dispatcher_switch_to_view(weebo->view_dispatcher, WeeboViewPopup);
  139. }
  140. bool weebo_scene_write_on_event(void* context, SceneManagerEvent event) {
  141. Weebo* weebo = context;
  142. bool consumed = false;
  143. if(event.type == SceneManagerEventTypeCustom) {
  144. scene_manager_set_scene_state(weebo->scene_manager, WeeboSceneWrite, event.event);
  145. if(event.event == WeeboCustomEventCardDetected) {
  146. popup_set_text(weebo->popup, "Card detected", 64, 36, AlignCenter, AlignTop);
  147. consumed = true;
  148. } else if(event.event == WeeboCustomEventWriteSuccess) {
  149. popup_set_text(weebo->popup, "Write success", 64, 36, AlignCenter, AlignTop);
  150. consumed = true;
  151. // TODO: push to new scene
  152. } else if(event.event == WeeboCustomEventWrongCard) {
  153. popup_set_text(weebo->popup, "Wrong card", 64, 36, AlignCenter, AlignTop);
  154. consumed = true;
  155. }
  156. }
  157. return consumed;
  158. }
  159. void weebo_scene_write_on_exit(void* context) {
  160. Weebo* weebo = context;
  161. if(weebo->poller) {
  162. nfc_poller_stop(weebo->poller);
  163. nfc_poller_free(weebo->poller);
  164. weebo->poller = NULL;
  165. }
  166. popup_reset(weebo->popup);
  167. weebo_blink_stop(weebo);
  168. }