totp_scene_authenticate.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include "totp_scene_authenticate.h"
  2. #include <dialogs/dialogs.h>
  3. #include <totp_icons.h>
  4. #include "../../../types/common.h"
  5. #include "../../constants.h"
  6. #include "../../../services/config/config.h"
  7. #include "../../scene_director.h"
  8. #include "../../totp_scenes_enum.h"
  9. #include "../../../services/crypto/crypto_facade.h"
  10. #include "../../../types/user_pin_codes.h"
  11. #define MAX_CODE_LENGTH CRYPTO_IV_LENGTH
  12. static const uint8_t PIN_ASTERISK_RADIUS = 3;
  13. static const uint8_t PIN_ASTERISK_STEP = (PIN_ASTERISK_RADIUS << 1) + 2;
  14. typedef struct {
  15. TotpUserPinCode code_input[MAX_CODE_LENGTH];
  16. uint8_t code_length;
  17. } SceneState;
  18. void totp_scene_authenticate_activate(PluginState* plugin_state) {
  19. SceneState* scene_state = malloc(sizeof(SceneState));
  20. furi_check(scene_state != NULL);
  21. scene_state->code_length = 0;
  22. memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH);
  23. plugin_state->current_scene_state = scene_state;
  24. memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH);
  25. }
  26. void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state) {
  27. const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
  28. int v_shift = 0;
  29. if(scene_state->code_length > 0) {
  30. v_shift = -10;
  31. }
  32. if(plugin_state->crypto_settings.crypto_verify_data == NULL) {
  33. canvas_draw_str_aligned(
  34. canvas,
  35. SCREEN_WIDTH_CENTER,
  36. SCREEN_HEIGHT_CENTER - 10 + v_shift,
  37. AlignCenter,
  38. AlignCenter,
  39. "Use arrow keys");
  40. canvas_draw_str_aligned(
  41. canvas,
  42. SCREEN_WIDTH_CENTER,
  43. SCREEN_HEIGHT_CENTER + 5 + v_shift,
  44. AlignCenter,
  45. AlignCenter,
  46. "to setup new PIN");
  47. } else {
  48. canvas_draw_str_aligned(
  49. canvas,
  50. SCREEN_WIDTH_CENTER,
  51. SCREEN_HEIGHT_CENTER + v_shift,
  52. AlignCenter,
  53. AlignCenter,
  54. "Use arrow keys to enter PIN");
  55. }
  56. if(scene_state->code_length > 0) {
  57. uint8_t left_start_x = ((scene_state->code_length - 1) * PIN_ASTERISK_STEP) >> 1;
  58. for(uint8_t i = 0; i < scene_state->code_length; i++) {
  59. canvas_draw_disc(
  60. canvas,
  61. SCREEN_WIDTH_CENTER - left_start_x + i * PIN_ASTERISK_STEP,
  62. SCREEN_HEIGHT_CENTER + 10,
  63. PIN_ASTERISK_RADIUS);
  64. }
  65. }
  66. }
  67. bool totp_scene_authenticate_handle_event(
  68. const PluginEvent* const event,
  69. PluginState* plugin_state) {
  70. if(event->type != EventTypeKey) {
  71. return true;
  72. }
  73. if(event->input.type == InputTypeShort && event->input.key == InputKeyBack) {
  74. return false;
  75. }
  76. SceneState* scene_state = plugin_state->current_scene_state;
  77. if((event->input.type == InputTypeLong || event->input.type == InputTypeRepeat) &&
  78. event->input.key == InputKeyBack) {
  79. if(scene_state->code_length > 0) {
  80. scene_state->code_input[scene_state->code_length - 1] = 0;
  81. scene_state->code_length--;
  82. }
  83. } else if(event->input.type == InputTypePress) {
  84. switch(event->input.key) {
  85. case InputKeyUp:
  86. if(scene_state->code_length < MAX_CODE_LENGTH) {
  87. scene_state->code_input[scene_state->code_length] = PinCodeArrowUp;
  88. scene_state->code_length++;
  89. }
  90. break;
  91. case InputKeyDown:
  92. if(scene_state->code_length < MAX_CODE_LENGTH) {
  93. scene_state->code_input[scene_state->code_length] = PinCodeArrowDown;
  94. scene_state->code_length++;
  95. }
  96. break;
  97. case InputKeyRight:
  98. if(scene_state->code_length < MAX_CODE_LENGTH) {
  99. scene_state->code_input[scene_state->code_length] = PinCodeArrowRight;
  100. scene_state->code_length++;
  101. }
  102. break;
  103. case InputKeyLeft:
  104. if(scene_state->code_length < MAX_CODE_LENGTH) {
  105. scene_state->code_input[scene_state->code_length] = PinCodeArrowLeft;
  106. scene_state->code_length++;
  107. }
  108. break;
  109. case InputKeyOk: {
  110. CryptoSeedIVResult seed_result = totp_crypto_seed_iv(
  111. &plugin_state->crypto_settings,
  112. &scene_state->code_input[0],
  113. scene_state->code_length);
  114. if(seed_result & CryptoSeedIVResultFlagSuccess &&
  115. seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) {
  116. totp_config_file_update_crypto_signatures(plugin_state);
  117. }
  118. if(totp_crypto_verify_key(&plugin_state->crypto_settings)) {
  119. totp_config_file_ensure_latest_encryption(
  120. plugin_state, &scene_state->code_input[0], scene_state->code_length);
  121. totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken);
  122. } else {
  123. memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH);
  124. memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH);
  125. scene_state->code_length = 0;
  126. DialogMessage* message = dialog_message_alloc();
  127. dialog_message_set_buttons(message, "Try again", NULL, NULL);
  128. dialog_message_set_header(
  129. message,
  130. "You entered\ninvalid PIN",
  131. SCREEN_WIDTH_CENTER - 25,
  132. SCREEN_HEIGHT_CENTER - 5,
  133. AlignCenter,
  134. AlignCenter);
  135. dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17);
  136. dialog_message_show(plugin_state->dialogs_app, message);
  137. dialog_message_free(message);
  138. }
  139. break;
  140. }
  141. case InputKeyBack:
  142. break;
  143. default:
  144. break;
  145. }
  146. }
  147. return true;
  148. }
  149. void totp_scene_authenticate_deactivate(PluginState* plugin_state) {
  150. if(plugin_state->current_scene_state == NULL) return;
  151. free(plugin_state->current_scene_state);
  152. plugin_state->current_scene_state = NULL;
  153. }