picopass_scene_parse_sio.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include "../picopass_i.h"
  2. #include <dolphin/dolphin.h>
  3. #define ASN_EMIT_DEBUG 0
  4. #include <SIO.h>
  5. #define TAG "PicopassSceneParseSIO"
  6. static char asn1_log[128] = {0};
  7. static int picopass_scene_parse_sio_callback(const void* buffer, size_t size, void* app_key) {
  8. if(app_key) {
  9. char* str = (char*)app_key;
  10. size_t next = strlen(str);
  11. strncpy(str + next, buffer, size);
  12. } else {
  13. uint8_t next = strlen(asn1_log);
  14. strncpy(asn1_log + next, buffer, size);
  15. }
  16. return 0;
  17. }
  18. void picopass_scene_parse_sio_widget_callback(GuiButtonType result, InputType type, void* context) {
  19. Picopass* picopass = context;
  20. if(type == InputTypeShort) {
  21. view_dispatcher_send_custom_event(picopass->view_dispatcher, result);
  22. }
  23. }
  24. void picopass_scene_parse_sio_on_enter(void* context) {
  25. Picopass* picopass = context;
  26. PicopassDevice* dev = picopass->dev;
  27. PicopassPacs* pacs = &dev->dev_data.pacs;
  28. PicopassBlock* card_data = dev->dev_data.card_data;
  29. furi_string_reset(picopass->text_box_store);
  30. FuriString* str = picopass->text_box_store;
  31. char sioDebug[384] = {0};
  32. uint8_t start_block = 0;
  33. // TODO: save SR vs SE more properly
  34. if(pacs->sio) { // SR
  35. start_block = 10;
  36. } else if(pacs->se_enabled) { //SE
  37. start_block = 6;
  38. }
  39. uint8_t sio_buffer[128];
  40. size_t sio_length = card_data[start_block].data[1];
  41. size_t block_count = (sio_length + PICOPASS_BLOCK_LEN - 1) / PICOPASS_BLOCK_LEN;
  42. for(uint8_t i = 0; i < block_count; i++) {
  43. memcpy(
  44. sio_buffer + (i * PICOPASS_BLOCK_LEN),
  45. card_data[start_block + i].data,
  46. PICOPASS_BLOCK_LEN);
  47. }
  48. SIO_t* sio = 0;
  49. sio = calloc(1, sizeof *sio);
  50. assert(sio);
  51. asn_dec_rval_t rval = asn_decode(
  52. 0, ATS_DER, &asn_DEF_SIO, (void**)&sio, sio_buffer, block_count * PICOPASS_BLOCK_LEN);
  53. if(rval.code == RC_OK) {
  54. (&asn_DEF_SIO)
  55. ->op->print_struct(&asn_DEF_SIO, sio, 1, picopass_scene_parse_sio_callback, sioDebug);
  56. if(strlen(sioDebug) > 0) {
  57. furi_string_cat_printf(str, sioDebug);
  58. FURI_LOG_D(TAG, "SIO: %s", sioDebug);
  59. }
  60. } else {
  61. FURI_LOG_W(TAG, "Failed to decode SIO: %d. %d bytes consumed", rval.code, rval.consumed);
  62. furi_string_cat_printf(str, "Failed to decode SIO");
  63. }
  64. ASN_STRUCT_FREE(asn_DEF_SIO, sio);
  65. text_box_set_font(picopass->text_box, TextBoxFontText);
  66. text_box_set_text(picopass->text_box, furi_string_get_cstr(picopass->text_box_store));
  67. view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewTextBox);
  68. }
  69. bool picopass_scene_parse_sio_on_event(void* context, SceneManagerEvent event) {
  70. Picopass* picopass = context;
  71. bool consumed = false;
  72. if(event.type == SceneManagerEventTypeCustom) {
  73. if(event.event == GuiButtonTypeLeft) {
  74. consumed = scene_manager_previous_scene(picopass->scene_manager);
  75. }
  76. } else if(event.type == SceneManagerEventTypeBack) {
  77. consumed = scene_manager_previous_scene(picopass->scene_manager);
  78. }
  79. return consumed;
  80. }
  81. void picopass_scene_parse_sio_on_exit(void* context) {
  82. Picopass* picopass = context;
  83. // Clear views
  84. text_box_reset(picopass->text_box);
  85. }