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