totp_scene_authenticate.c 6.0 KB

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