pin.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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(PipeSide* pipe, 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(pipe_receive(pipe, &c, 1) == 1) {
  41. if(c == CliKeyEsc) {
  42. uint8_t c2;
  43. uint8_t c3;
  44. if(pipe_receive(pipe, &c2, 1) == 1 && pipe_receive(pipe, &c3, 1) == 1 && c2 == 0x5b) {
  45. uint8_t code = totp_cli_key_to_pin_code(c3);
  46. if(code > 0) {
  47. pin[*pin_length] = code;
  48. *pin_length = *pin_length + 1;
  49. putc('*', stdout);
  50. fflush(stdout);
  51. }
  52. }
  53. } else if(c == CliKeyETX) {
  54. TOTP_CLI_DELETE_CURRENT_LINE();
  55. TOTP_CLI_PRINTF_INFO("Cancelled by user\r\n");
  56. return false;
  57. } else if(c == CliKeyBackspace || c == CliKeyDEL) {
  58. if(*pin_length > 0) {
  59. *pin_length = *pin_length - 1;
  60. pin[*pin_length] = 0;
  61. TOTP_CLI_DELETE_LAST_CHAR();
  62. }
  63. } else if(c == CliKeyCR) {
  64. TOTP_CLI_NL();
  65. break;
  66. }
  67. }
  68. TOTP_CLI_DELETE_LAST_LINE();
  69. return true;
  70. }
  71. static void handle(PluginState* plugin_state, FuriString* args, PipeSide* pipe) {
  72. UNUSED(plugin_state);
  73. FuriString* temp_str = furi_string_alloc();
  74. bool do_change = false;
  75. bool do_remove = false;
  76. uint8_t crypto_key_slot = plugin_state->crypto_settings.crypto_key_slot;
  77. bool arguments_parsed = true;
  78. while(args_read_string_and_trim(args, temp_str)) {
  79. if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_SET) == 0) {
  80. do_change = true;
  81. } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE) == 0) {
  82. do_remove = true;
  83. } else if(
  84. furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT_PREFIX) ==
  85. 0) {
  86. if(!args_read_uint8_and_trim(args, &crypto_key_slot) ||
  87. !totp_crypto_check_key_slot(crypto_key_slot)) {
  88. TOTP_CLI_PRINTF_ERROR("Slot \"%" PRIu8 "\" can not be used\r\n", crypto_key_slot);
  89. arguments_parsed = false;
  90. break;
  91. }
  92. } else {
  93. TOTP_CLI_PRINT_INVALID_ARGUMENTS();
  94. arguments_parsed = false;
  95. break;
  96. }
  97. }
  98. if(!(do_change || do_remove) || (do_change && do_remove)) {
  99. TOTP_CLI_PRINT_INVALID_ARGUMENTS();
  100. arguments_parsed = false;
  101. }
  102. if(arguments_parsed && totp_cli_ensure_authenticated(plugin_state, pipe)) {
  103. TOTP_CLI_LOCK_UI(plugin_state);
  104. do {
  105. uint8_t new_pin[CRYPTO_IV_LENGTH];
  106. memset(&new_pin[0], 0, CRYPTO_IV_LENGTH);
  107. uint8_t new_pin_length = 0;
  108. if(do_change) {
  109. if(!totp_cli_read_pin(pipe, &new_pin[0], &new_pin_length)) {
  110. memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH);
  111. break;
  112. }
  113. } else if(do_remove) {
  114. new_pin_length = 0;
  115. memset(&new_pin[0], 0, CRYPTO_IV_LENGTH);
  116. }
  117. char* backup_path = totp_config_file_backup(plugin_state);
  118. if(backup_path != NULL) {
  119. TOTP_CLI_PRINTF_WARNING("Backup conf file %s has been created\r\n", backup_path);
  120. TOTP_CLI_PRINTF_WARNING(
  121. "Once you make sure everything is fine and works as expected, please delete this backup file\r\n");
  122. free(backup_path);
  123. } else {
  124. memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH);
  125. TOTP_CLI_PRINTF_ERROR(
  126. "An error has occurred during taking backup of config file\r\n");
  127. break;
  128. }
  129. TOTP_CLI_PRINTF("Encrypting...\r\n");
  130. bool update_result = totp_config_file_update_encryption(
  131. plugin_state, crypto_key_slot, new_pin, new_pin_length);
  132. memset_s(&new_pin[0], CRYPTO_IV_LENGTH, 0, CRYPTO_IV_LENGTH);
  133. TOTP_CLI_DELETE_LAST_LINE();
  134. if(update_result) {
  135. if(do_change) {
  136. TOTP_CLI_PRINTF_SUCCESS("PIN has been successfully changed\r\n");
  137. } else if(do_remove) {
  138. TOTP_CLI_PRINTF_SUCCESS("PIN has been successfully removed\r\n");
  139. }
  140. } else {
  141. TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
  142. }
  143. } while(false);
  144. TOTP_CLI_UNLOCK_UI(plugin_state);
  145. }
  146. furi_string_free(temp_str);
  147. }
  148. static const CliPlugin plugin = {.name = "TOTP CLI Plugin: PIN", .handle = &handle};
  149. static const FlipperAppPluginDescriptor plugin_descriptor = {
  150. .appid = PLUGIN_APP_ID,
  151. .ep_api_version = PLUGIN_API_VERSION,
  152. .entry_point = &plugin,
  153. };
  154. const FlipperAppPluginDescriptor* totp_cli_pin_plugin_ep() {
  155. return &plugin_descriptor;
  156. }