export.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include <lib/toolbox/args.h>
  2. #include <flipper_application/flipper_application.h>
  3. #include "../../../lib/polyfills/memset_s.h"
  4. #include "../../../services/config/config.h"
  5. #include "../../../services/crypto/crypto_facade.h"
  6. #include "../../../ui/scene_director.h"
  7. #include "../../cli_helpers.h"
  8. #include "../../cli_plugin_interface.h"
  9. #include "../../cli_shared_methods.h"
  10. static const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
  11. static void print_as_base32(const uint8_t* data, size_t length) {
  12. int buffer = data[0];
  13. size_t next = 1;
  14. int bitsLeft = 8;
  15. while(bitsLeft > 0 || next < length) {
  16. if(bitsLeft < 5) {
  17. if(next < length) {
  18. buffer <<= 8;
  19. buffer |= data[next++] & 0xFF;
  20. bitsLeft += 8;
  21. } else {
  22. int pad = 5 - bitsLeft;
  23. buffer <<= pad;
  24. bitsLeft += pad; //-V1026
  25. }
  26. }
  27. int index = 0x1F & (buffer >> (bitsLeft - 5));
  28. bitsLeft -= 5;
  29. putchar(BASE32_ALPHABET[index]);
  30. }
  31. }
  32. static void print_uri_component(const char* data, size_t length) {
  33. const char* c_ptr = data;
  34. const char* last_ptr = data + length;
  35. while(c_ptr < last_ptr) {
  36. const char c = *c_ptr;
  37. if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
  38. c == '-' || c == '_') {
  39. putchar(c);
  40. } else {
  41. printf("%%%x", c);
  42. }
  43. c_ptr++;
  44. }
  45. }
  46. static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
  47. UNUSED(args);
  48. UNUSED(plugin_state);
  49. if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
  50. return;
  51. }
  52. TOTP_CLI_PRINTF_WARNING("WARNING!\r\n");
  53. TOTP_CLI_PRINTF_WARNING(
  54. "ALL THE INFORMATION (INCL. UNENCRYPTED SECRET) ABOUT ALL THE TOKENS WILL BE EXPORTED AND PRINTED TO THE CONSOLE.\r\n");
  55. TOTP_CLI_PRINTF_WARNING("Confirm? [y/n]\r\n");
  56. fflush(stdout);
  57. char user_pick;
  58. do {
  59. user_pick = tolower(cli_getc(cli));
  60. } while(user_pick != 'y' && user_pick != 'n' && user_pick != CliSymbolAsciiCR &&
  61. user_pick != CliSymbolAsciiETX && user_pick != CliSymbolAsciiEsc);
  62. if(user_pick != 'y' && user_pick != CliSymbolAsciiCR) {
  63. TOTP_CLI_PRINTF_INFO("User has not confirmed\r\n");
  64. return;
  65. }
  66. TokenInfoIteratorContext* iterator_context =
  67. totp_config_get_token_iterator_context(plugin_state);
  68. size_t total_count = totp_token_info_iterator_get_total_count(iterator_context);
  69. TOTP_CLI_LOCK_UI(plugin_state);
  70. size_t original_index = totp_token_info_iterator_get_current_token_index(iterator_context);
  71. cli_nl(NULL);
  72. TOTP_CLI_PRINTF("# --- EXPORT LIST BEGIN ---\r\n");
  73. for(size_t i = 0; i < total_count; i++) {
  74. totp_token_info_iterator_go_to(iterator_context, i);
  75. const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context);
  76. TOTP_CLI_PRINTF("otpauth://%s/", token_info_get_type_as_cstr(token_info));
  77. print_uri_component(
  78. furi_string_get_cstr(token_info->name), furi_string_size(token_info->name));
  79. TOTP_CLI_PRINTF("?secret=");
  80. size_t key_length;
  81. uint8_t* key = totp_crypto_decrypt(
  82. token_info->token,
  83. token_info->token_length,
  84. &plugin_state->crypto_settings,
  85. &key_length);
  86. print_as_base32(key, key_length);
  87. memset_s(key, key_length, 0, key_length);
  88. free(key);
  89. TOTP_CLI_PRINTF("&algorithm=%s", token_info_get_algo_as_cstr(token_info));
  90. TOTP_CLI_PRINTF("&digits=%" PRIu8, token_info->digits);
  91. if(token_info->type == TokenTypeHOTP) {
  92. TOTP_CLI_PRINTF("&counter=%" PRIu64, token_info->counter);
  93. } else {
  94. TOTP_CLI_PRINTF("&period=%" PRIu8, token_info->duration);
  95. }
  96. cli_nl(NULL);
  97. }
  98. TOTP_CLI_PRINTF("# --- EXPORT LIST END ---\r\n\r\n");
  99. totp_token_info_iterator_go_to(iterator_context, original_index);
  100. TOTP_CLI_UNLOCK_UI(plugin_state);
  101. }
  102. static const CliPlugin plugin = {.name = "TOTP CLI Plugin: Export", .handle = &handle};
  103. static const FlipperAppPluginDescriptor plugin_descriptor = {
  104. .appid = PLUGIN_APP_ID,
  105. .ep_api_version = PLUGIN_API_VERSION,
  106. .entry_point = &plugin,
  107. };
  108. const FlipperAppPluginDescriptor* totp_cli_export_plugin_ep() {
  109. return &plugin_descriptor;
  110. }