pin.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include <flipper_application/flipper_application.h>
  2. #include <lib/toolbox/args.h>
  3. #include "../../cli_helpers.h"
  4. #include "../../cli_shared_methods.h"
  5. #include "../../cli_plugin_interface.h"
  6. #include "../../../types/token_info.h"
  7. #include "../../../types/user_pin_codes.h"
  8. #include "../../../services/config/config.h"
  9. #include "../../../services/crypto/crypto_facade.h"
  10. #include "../../../ui/scene_director.h"
  11. #include "../../../lib/polyfills/memset_s.h"
  12. #define TOTP_CLI_COMMAND_PIN_COMMAND_SET "set"
  13. #define TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE "remove"
  14. #define TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT_PREFIX "-c"
  15. static inline uint8_t totp_cli_key_to_pin_code(uint8_t key) {
  16. uint8_t code = 0;
  17. switch(key) {
  18. case 0x44: // left
  19. code = PinCodeArrowLeft;
  20. break;
  21. case 0x41: // up
  22. code = PinCodeArrowUp;
  23. break;
  24. case 0x43: // right
  25. code = PinCodeArrowRight;
  26. break;
  27. case 0x42: // down
  28. code = PinCodeArrowDown;
  29. break;
  30. default:
  31. break;
  32. }
  33. return code;
  34. }
  35. static bool totp_cli_read_pin(Cli* cli, uint8_t* pin, uint8_t* pin_length) {
  36. TOTP_CLI_PRINTF("Enter new PIN (use arrow keys on your keyboard): ");
  37. fflush(stdout);
  38. uint8_t c;
  39. *pin_length = 0;
  40. while(cli_read(cli, &c, 1) == 1) {
  41. if(c == CliSymbolAsciiEsc) {
  42. uint8_t c2;
  43. uint8_t c3;
  44. if(cli_read_timeout(cli, &c2, 1, 0) == 1 && cli_read_timeout(cli, &c3, 1, 0) == 1 &&
  45. c2 == 0x5b) {
  46. uint8_t code = totp_cli_key_to_pin_code(c3);
  47. if(code > 0) {
  48. pin[*pin_length] = code;
  49. *pin_length = *pin_length + 1;
  50. putc('*', stdout);
  51. fflush(stdout);
  52. }
  53. }
  54. } else if(c == CliSymbolAsciiETX) {
  55. TOTP_CLI_DELETE_CURRENT_LINE();
  56. TOTP_CLI_PRINTF_INFO("Cancelled by user\r\n");
  57. return false;
  58. } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
  59. if(*pin_length > 0) {
  60. *pin_length = *pin_length - 1;
  61. pin[*pin_length] = 0;
  62. TOTP_CLI_DELETE_LAST_CHAR();
  63. }
  64. } else if(c == CliSymbolAsciiCR) {
  65. cli_nl();
  66. break;
  67. }
  68. }
  69. TOTP_CLI_DELETE_LAST_LINE();
  70. return true;
  71. }
  72. static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
  73. UNUSED(plugin_state);
  74. FuriString* temp_str = furi_string_alloc();
  75. bool do_change = false;
  76. bool do_remove = false;
  77. uint8_t crypto_key_slot = plugin_state->crypto_settings.crypto_key_slot;
  78. bool arguments_parsed = true;
  79. while(args_read_string_and_trim(args, temp_str)) {
  80. if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_SET) == 0) {
  81. do_change = true;
  82. } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE) == 0) {
  83. do_remove = true;
  84. } else if(
  85. furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT_PREFIX) ==
  86. 0) {
  87. if(!args_read_uint8_and_trim(args, &crypto_key_slot) ||
  88. !totp_crypto_check_key_slot(crypto_key_slot)) {
  89. TOTP_CLI_PRINTF_ERROR("Slot \"%" PRIu8 "\" can not be used\r\n", crypto_key_slot);
  90. arguments_parsed = false;
  91. break;
  92. }
  93. } else {
  94. TOTP_CLI_PRINT_INVALID_ARGUMENTS();
  95. arguments_parsed = false;
  96. break;
  97. }
  98. }
  99. if(!(do_change || do_remove) || (do_change && do_remove)) {
  100. TOTP_CLI_PRINT_INVALID_ARGUMENTS();
  101. arguments_parsed = false;
  102. }
  103. if(arguments_parsed && totp_cli_ensure_authenticated(plugin_state, cli)) {
  104. TOTP_CLI_LOCK_UI(plugin_state);
  105. do {
  106. uint8_t new_pin[CRYPTO_IV_LENGTH];
  107. memset(&new_pin[0], 0, CRYPTO_IV_LENGTH);
  108. uint8_t new_pin_length = 0;
  109. if(do_change) {
  110. if(!totp_cli_read_pin(cli, &new_pin[0], &new_pin_length)) {
  111. memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH);
  112. break;
  113. }
  114. } else if(do_remove) {
  115. new_pin_length = 0;
  116. memset(&new_pin[0], 0, CRYPTO_IV_LENGTH);
  117. }
  118. char* backup_path = totp_config_file_backup(plugin_state);
  119. if(backup_path != NULL) {
  120. TOTP_CLI_PRINTF_WARNING("Backup conf file %s has been created\r\n", backup_path);
  121. TOTP_CLI_PRINTF_WARNING(
  122. "Once you make sure everything is fine and works as expected, please delete this backup file\r\n");
  123. free(backup_path);
  124. } else {
  125. memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH);
  126. TOTP_CLI_PRINTF_ERROR(
  127. "An error has occurred during taking backup of config file\r\n");
  128. break;
  129. }
  130. TOTP_CLI_PRINTF("Encrypting...\r\n");
  131. bool update_result = totp_config_file_update_encryption(
  132. plugin_state, crypto_key_slot, new_pin, new_pin_length);
  133. memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH);
  134. TOTP_CLI_DELETE_LAST_LINE();
  135. if(update_result) {
  136. if(do_change) {
  137. TOTP_CLI_PRINTF_SUCCESS("PIN has been successfully changed\r\n");
  138. } else if(do_remove) {
  139. TOTP_CLI_PRINTF_SUCCESS("PIN has been successfully removed\r\n");
  140. }
  141. } else {
  142. TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
  143. }
  144. } while(false);
  145. TOTP_CLI_UNLOCK_UI(plugin_state);
  146. }
  147. furi_string_free(temp_str);
  148. }
  149. static const CliPlugin plugin = {.name = "TOTP CLI Plugin: PIN", .handle = &handle};
  150. static const FlipperAppPluginDescriptor plugin_descriptor = {
  151. .appid = PLUGIN_APP_ID,
  152. .ep_api_version = PLUGIN_API_VERSION,
  153. .entry_point = &plugin,
  154. };
  155. const FlipperAppPluginDescriptor* totp_cli_pin_plugin_ep() {
  156. return &plugin_descriptor;
  157. }