totp_scene_authenticate.c 5.5 KB

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