iclass_elite_dict.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #include "iclass_elite_dict.h"
  2. #include <lib/toolbox/args.h>
  3. #include <lib/flipper_format/flipper_format.h>
  4. #define ICLASS_ELITE_DICT_FLIPPER_NAME APP_ASSETS_PATH("iclass_elite_dict.txt")
  5. #define ICLASS_STANDARD_DICT_FLIPPER_NAME APP_ASSETS_PATH("iclass_standard_dict.txt")
  6. #define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt")
  7. #define TAG "IclassEliteDict"
  8. #define ICLASS_ELITE_KEY_LINE_LEN (17)
  9. #define ICLASS_ELITE_KEY_LEN (8)
  10. struct IclassEliteDict {
  11. Stream* stream;
  12. uint32_t total_keys;
  13. };
  14. bool iclass_elite_dict_check_presence(IclassEliteDictType dict_type) {
  15. Storage* storage = furi_record_open(RECORD_STORAGE);
  16. bool dict_present = false;
  17. if(dict_type == IclassEliteDictTypeFlipper) {
  18. dict_present =
  19. (storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_NAME, NULL) == FSE_OK);
  20. } else if(dict_type == IclassEliteDictTypeUser) {
  21. dict_present = (storage_common_stat(storage, ICLASS_ELITE_DICT_USER_NAME, NULL) == FSE_OK);
  22. } else if(dict_type == IclassStandardDictTypeFlipper) {
  23. dict_present =
  24. (storage_common_stat(storage, ICLASS_STANDARD_DICT_FLIPPER_NAME, NULL) == FSE_OK);
  25. }
  26. furi_record_close(RECORD_STORAGE);
  27. return dict_present;
  28. }
  29. IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type) {
  30. IclassEliteDict* dict = malloc(sizeof(IclassEliteDict));
  31. Storage* storage = furi_record_open(RECORD_STORAGE);
  32. dict->stream = buffered_file_stream_alloc(storage);
  33. FuriString* next_line = furi_string_alloc();
  34. bool dict_loaded = false;
  35. do {
  36. if(dict_type == IclassEliteDictTypeFlipper) {
  37. if(!buffered_file_stream_open(
  38. dict->stream, ICLASS_ELITE_DICT_FLIPPER_NAME, FSAM_READ, FSOM_OPEN_EXISTING)) {
  39. buffered_file_stream_close(dict->stream);
  40. break;
  41. }
  42. } else if(dict_type == IclassEliteDictTypeUser) {
  43. if(!buffered_file_stream_open(
  44. dict->stream, ICLASS_ELITE_DICT_USER_NAME, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) {
  45. buffered_file_stream_close(dict->stream);
  46. break;
  47. }
  48. } else if(dict_type == IclassStandardDictTypeFlipper) {
  49. if(!buffered_file_stream_open(
  50. dict->stream,
  51. ICLASS_STANDARD_DICT_FLIPPER_NAME,
  52. FSAM_READ,
  53. FSOM_OPEN_EXISTING)) {
  54. buffered_file_stream_close(dict->stream);
  55. break;
  56. }
  57. }
  58. // Read total amount of keys
  59. while(true) { //-V547
  60. if(!stream_read_line(dict->stream, next_line)) break;
  61. if(furi_string_get_char(next_line, 0) == '#') continue;
  62. if(furi_string_size(next_line) != ICLASS_ELITE_KEY_LINE_LEN) continue;
  63. dict->total_keys++;
  64. }
  65. furi_string_reset(next_line);
  66. stream_rewind(dict->stream);
  67. dict_loaded = true;
  68. FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", dict->total_keys);
  69. } while(false);
  70. if(!dict_loaded) { //-V547
  71. buffered_file_stream_close(dict->stream);
  72. free(dict);
  73. dict = NULL;
  74. }
  75. furi_record_close(RECORD_STORAGE);
  76. furi_string_free(next_line);
  77. return dict;
  78. }
  79. void iclass_elite_dict_free(IclassEliteDict* dict) {
  80. furi_assert(dict);
  81. furi_assert(dict->stream);
  82. buffered_file_stream_close(dict->stream);
  83. stream_free(dict->stream);
  84. free(dict);
  85. }
  86. uint32_t iclass_elite_dict_get_total_keys(IclassEliteDict* dict) {
  87. furi_assert(dict);
  88. return dict->total_keys;
  89. }
  90. bool iclass_elite_dict_get_next_key(IclassEliteDict* dict, uint8_t* key) {
  91. furi_assert(dict);
  92. furi_assert(dict->stream);
  93. uint8_t key_byte_tmp = 0;
  94. FuriString* next_line = furi_string_alloc();
  95. bool key_read = false;
  96. *key = 0ULL;
  97. while(!key_read) {
  98. if(!stream_read_line(dict->stream, next_line)) break;
  99. if(furi_string_get_char(next_line, 0) == '#') continue;
  100. if(furi_string_size(next_line) != ICLASS_ELITE_KEY_LINE_LEN) continue;
  101. for(uint8_t i = 0; i < ICLASS_ELITE_KEY_LEN * 2; i += 2) {
  102. args_char_to_hex(
  103. furi_string_get_char(next_line, i),
  104. furi_string_get_char(next_line, i + 1),
  105. &key_byte_tmp);
  106. key[i / 2] = key_byte_tmp;
  107. }
  108. key_read = true;
  109. }
  110. furi_string_free(next_line);
  111. return key_read;
  112. }
  113. bool iclass_elite_dict_rewind(IclassEliteDict* dict) {
  114. furi_assert(dict);
  115. furi_assert(dict->stream);
  116. return stream_rewind(dict->stream);
  117. }
  118. bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key) {
  119. furi_assert(dict);
  120. furi_assert(dict->stream);
  121. FuriString* key_str = furi_string_alloc();
  122. for(size_t i = 0; i < ICLASS_ELITE_KEY_LEN; i++) {
  123. furi_string_cat_printf(key_str, "%02X", key[i]);
  124. }
  125. furi_string_cat_printf(key_str, "\n");
  126. bool key_added = false;
  127. do {
  128. if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break;
  129. if(!stream_insert_string(dict->stream, key_str)) break;
  130. key_added = true;
  131. } while(false);
  132. furi_string_free(key_str);
  133. return key_added;
  134. }