|
|
@@ -2,19 +2,16 @@
|
|
|
#include <notification/notification.h>
|
|
|
#include <notification/notification_messages.h>
|
|
|
#include <totp_icons.h>
|
|
|
+#include <roll_value.h>
|
|
|
#include "totp_scene_generate_token.h"
|
|
|
#include "../../../types/token_info.h"
|
|
|
#include "../../../types/common.h"
|
|
|
#include "../../constants.h"
|
|
|
-#include "../../../services/totp/totp.h"
|
|
|
#include "../../../services/config/config.h"
|
|
|
-#include "../../../services/crypto/crypto.h"
|
|
|
-#include "../../../services/convert/convert.h"
|
|
|
-#include "../../../lib/polyfills/memset_s.h"
|
|
|
-#include "../../../lib/roll_value/roll_value.h"
|
|
|
#include "../../scene_director.h"
|
|
|
#include "../token_menu/totp_scene_token_menu.h"
|
|
|
#include "../../../features_config.h"
|
|
|
+#include "../../../workers/generate_totp_code/generate_totp_code.h"
|
|
|
#include "../../../workers/usb_type_code/usb_type_code.h"
|
|
|
#ifdef TOTP_BADBT_TYPE_ENABLED
|
|
|
#include "../../../workers/bt_type_code/bt_type_code.h"
|
|
|
@@ -23,18 +20,18 @@
|
|
|
|
|
|
#define PROGRESS_BAR_MARGIN (3)
|
|
|
#define PROGRESS_BAR_HEIGHT (4)
|
|
|
-static const char* STEAM_ALGO_ALPHABET = "23456789BCDFGHJKMNPQRTVWXY";
|
|
|
|
|
|
typedef struct {
|
|
|
uint16_t current_token_index;
|
|
|
char last_code[TOTP_TOKEN_DIGITS_MAX_COUNT + 1];
|
|
|
- bool need_token_update;
|
|
|
TokenInfo* current_token;
|
|
|
- uint32_t last_token_gen_time;
|
|
|
TotpUsbTypeCodeWorkerContext* usb_type_code_worker_context;
|
|
|
NotificationMessage const** notification_sequence_new_token;
|
|
|
- NotificationMessage const** notification_sequence_badusb;
|
|
|
+ NotificationMessage const** notification_sequence_automation;
|
|
|
FuriMutex* last_code_update_sync;
|
|
|
+ TotpGenerateCodeWorkerContext* generate_code_worker_context;
|
|
|
+ uint8_t progress_bar_x;
|
|
|
+ uint8_t progress_bar_width;
|
|
|
} SceneState;
|
|
|
|
|
|
static const NotificationSequence*
|
|
|
@@ -80,7 +77,7 @@ static const NotificationSequence*
|
|
|
|
|
|
static const NotificationSequence*
|
|
|
get_notification_sequence_automation(const PluginState* plugin_state, SceneState* scene_state) {
|
|
|
- if(scene_state->notification_sequence_badusb == NULL) {
|
|
|
+ if(scene_state->notification_sequence_automation == NULL) {
|
|
|
uint8_t i = 0;
|
|
|
uint8_t length = 3;
|
|
|
if(plugin_state->notification_method & NotificationMethodVibro) {
|
|
|
@@ -91,84 +88,46 @@ static const NotificationSequence*
|
|
|
length += 6;
|
|
|
}
|
|
|
|
|
|
- scene_state->notification_sequence_badusb = malloc(sizeof(void*) * length);
|
|
|
- furi_check(scene_state->notification_sequence_badusb != NULL);
|
|
|
+ scene_state->notification_sequence_automation = malloc(sizeof(void*) * length);
|
|
|
+ furi_check(scene_state->notification_sequence_automation != NULL);
|
|
|
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_blue_255;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_blue_255;
|
|
|
if(plugin_state->notification_method & NotificationMethodVibro) {
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_vibro_on;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_vibro_on;
|
|
|
}
|
|
|
|
|
|
if(plugin_state->notification_method & NotificationMethodSound) {
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_note_d5; //-V525
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_delay_50;
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_note_e4;
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_delay_50;
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_note_f3;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_note_d5; //-V525
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_delay_50;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_note_e4;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_delay_50;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_note_f3;
|
|
|
}
|
|
|
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_delay_50;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_delay_50;
|
|
|
|
|
|
if(plugin_state->notification_method & NotificationMethodVibro) {
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_vibro_off;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_vibro_off;
|
|
|
}
|
|
|
|
|
|
if(plugin_state->notification_method & NotificationMethodSound) {
|
|
|
- scene_state->notification_sequence_badusb[i++] = &message_sound_off;
|
|
|
+ scene_state->notification_sequence_automation[i++] = &message_sound_off;
|
|
|
}
|
|
|
|
|
|
- scene_state->notification_sequence_badusb[i++] = NULL;
|
|
|
+ scene_state->notification_sequence_automation[i++] = NULL;
|
|
|
}
|
|
|
|
|
|
- return (NotificationSequence*)scene_state->notification_sequence_badusb;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
- int_token_to_str(uint64_t i_token_code, char* str, TokenDigitsCount len, TokenHashAlgo algo) {
|
|
|
- if(i_token_code == OTP_ERROR) {
|
|
|
- memset(&str[0], '-', len);
|
|
|
- } else {
|
|
|
- if(algo == STEAM) {
|
|
|
- for(uint8_t i = 0; i < len; i++) {
|
|
|
- str[i] = STEAM_ALGO_ALPHABET[i_token_code % 26];
|
|
|
- i_token_code = i_token_code / 26;
|
|
|
- }
|
|
|
- } else {
|
|
|
- for(int8_t i = len - 1; i >= 0; i--) {
|
|
|
- str[i] = CONVERT_DIGIT_TO_CHAR(i_token_code % 10);
|
|
|
- i_token_code = i_token_code / 10;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- str[len] = '\0';
|
|
|
-}
|
|
|
-
|
|
|
-static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
|
|
|
- switch(algo) {
|
|
|
- case SHA1:
|
|
|
- case STEAM:
|
|
|
- return TOTP_ALGO_SHA1;
|
|
|
- case SHA256:
|
|
|
- return TOTP_ALGO_SHA256;
|
|
|
- case SHA512:
|
|
|
- return TOTP_ALGO_SHA512;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return NULL;
|
|
|
+ return (NotificationSequence*)scene_state->notification_sequence_automation;
|
|
|
}
|
|
|
|
|
|
static void update_totp_params(PluginState* const plugin_state) {
|
|
|
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
|
|
|
|
|
|
if(scene_state->current_token_index < plugin_state->tokens_count) {
|
|
|
- TokenInfo* tokenInfo =
|
|
|
+ scene_state->current_token =
|
|
|
list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data;
|
|
|
-
|
|
|
- scene_state->need_token_update = true;
|
|
|
- scene_state->current_token = tokenInfo;
|
|
|
+ totp_generate_code_worker_notify(
|
|
|
+ scene_state->generate_code_worker_context, TotpGenerateCodeWorkerEventForceUpdate);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -194,6 +153,24 @@ static void draw_totp_code(Canvas* const canvas, const SceneState* const scene_s
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void on_new_token_code_generated(bool time_left, void* context) {
|
|
|
+ if(time_left) {
|
|
|
+ PluginState* plugin_state = context;
|
|
|
+ notification_message(
|
|
|
+ plugin_state->notification_app,
|
|
|
+ get_notification_sequence_new_token(plugin_state, plugin_state->current_scene_state));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void on_code_lifetime_updated_generated(float code_lifetime_percent, void* context) {
|
|
|
+ SceneState* scene_state = context;
|
|
|
+ scene_state->progress_bar_width =
|
|
|
+ (uint8_t)((float)(SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1)) * code_lifetime_percent);
|
|
|
+ scene_state->progress_bar_x =
|
|
|
+ ((SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1) - scene_state->progress_bar_width) >> 1) +
|
|
|
+ PROGRESS_BAR_MARGIN;
|
|
|
+}
|
|
|
+
|
|
|
void totp_scene_generate_token_activate(
|
|
|
PluginState* plugin_state,
|
|
|
const GenerateTokenSceneContext* context) {
|
|
|
@@ -231,15 +208,14 @@ void totp_scene_generate_token_activate(
|
|
|
} else {
|
|
|
scene_state->current_token_index = context->current_token_index;
|
|
|
}
|
|
|
- scene_state->need_token_update = true;
|
|
|
+
|
|
|
plugin_state->current_scene_state = scene_state;
|
|
|
FURI_LOG_D(LOGGING_TAG, "Timezone set to: %f", (double)plugin_state->timezone_offset);
|
|
|
- update_totp_params(plugin_state);
|
|
|
|
|
|
scene_state->last_code_update_sync = furi_mutex_alloc(FuriMutexTypeNormal);
|
|
|
if(plugin_state->automation_method & AutomationMethodBadUsb) {
|
|
|
scene_state->usb_type_code_worker_context = totp_usb_type_code_worker_start(
|
|
|
- &scene_state->last_code[0],
|
|
|
+ scene_state->last_code,
|
|
|
TOTP_TOKEN_DIGITS_MAX_COUNT + 1,
|
|
|
scene_state->last_code_update_sync);
|
|
|
}
|
|
|
@@ -252,11 +228,28 @@ void totp_scene_generate_token_activate(
|
|
|
}
|
|
|
totp_bt_type_code_worker_start(
|
|
|
plugin_state->bt_type_code_worker_context,
|
|
|
- &scene_state->last_code[0],
|
|
|
+ scene_state->last_code,
|
|
|
TOTP_TOKEN_DIGITS_MAX_COUNT + 1,
|
|
|
scene_state->last_code_update_sync);
|
|
|
}
|
|
|
#endif
|
|
|
+
|
|
|
+ scene_state->generate_code_worker_context = totp_generate_code_worker_start(
|
|
|
+ scene_state->last_code,
|
|
|
+ &scene_state->current_token,
|
|
|
+ scene_state->last_code_update_sync,
|
|
|
+ plugin_state->timezone_offset,
|
|
|
+ plugin_state->iv);
|
|
|
+
|
|
|
+ totp_generate_code_worker_set_code_generated_handler(
|
|
|
+ scene_state->generate_code_worker_context, &on_new_token_code_generated, plugin_state);
|
|
|
+
|
|
|
+ totp_generate_code_worker_set_lifetime_changed_handler(
|
|
|
+ scene_state->generate_code_worker_context,
|
|
|
+ &on_code_lifetime_updated_generated,
|
|
|
+ scene_state);
|
|
|
+
|
|
|
+ update_totp_params(plugin_state);
|
|
|
}
|
|
|
|
|
|
void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state) {
|
|
|
@@ -278,54 +271,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
|
|
|
- FuriHalRtcDateTime curr_dt;
|
|
|
- furi_hal_rtc_get_datetime(&curr_dt);
|
|
|
- uint32_t curr_ts = furi_hal_rtc_datetime_to_timestamp(&curr_dt);
|
|
|
-
|
|
|
- bool is_new_token_time = curr_ts % scene_state->current_token->duration == 0;
|
|
|
- if(is_new_token_time && scene_state->last_token_gen_time != curr_ts) {
|
|
|
- scene_state->need_token_update = true;
|
|
|
- }
|
|
|
-
|
|
|
- if(scene_state->need_token_update) {
|
|
|
- scene_state->need_token_update = false;
|
|
|
- scene_state->last_token_gen_time = curr_ts;
|
|
|
-
|
|
|
- const TokenInfo* tokenInfo = scene_state->current_token;
|
|
|
-
|
|
|
- if(tokenInfo->token != NULL && tokenInfo->token_length > 0) {
|
|
|
- furi_mutex_acquire(scene_state->last_code_update_sync, FuriWaitForever);
|
|
|
- size_t key_length;
|
|
|
- uint8_t* key = totp_crypto_decrypt(
|
|
|
- tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
|
|
|
-
|
|
|
- int_token_to_str(
|
|
|
- totp_at(
|
|
|
- get_totp_algo_impl(tokenInfo->algo),
|
|
|
- key,
|
|
|
- key_length,
|
|
|
- curr_ts,
|
|
|
- plugin_state->timezone_offset,
|
|
|
- tokenInfo->duration),
|
|
|
- scene_state->last_code,
|
|
|
- tokenInfo->digits,
|
|
|
- tokenInfo->algo);
|
|
|
- memset_s(key, key_length, 0, key_length);
|
|
|
- free(key);
|
|
|
- } else {
|
|
|
- furi_mutex_acquire(scene_state->last_code_update_sync, FuriWaitForever);
|
|
|
- int_token_to_str(0, scene_state->last_code, tokenInfo->digits, tokenInfo->algo);
|
|
|
- }
|
|
|
-
|
|
|
- furi_mutex_release(scene_state->last_code_update_sync);
|
|
|
-
|
|
|
- if(is_new_token_time) {
|
|
|
- notification_message(
|
|
|
- plugin_state->notification_app,
|
|
|
- get_notification_sequence_new_token(plugin_state, scene_state));
|
|
|
- }
|
|
|
- }
|
|
|
+ const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
|
|
|
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
uint16_t token_name_width = canvas_string_width(canvas, scene_state->current_token->name);
|
|
|
@@ -353,17 +299,11 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
|
|
|
|
|
|
draw_totp_code(canvas, scene_state);
|
|
|
|
|
|
- const uint8_t TOKEN_LIFETIME = scene_state->current_token->duration;
|
|
|
- float percentDone = (float)(TOKEN_LIFETIME - curr_ts % TOKEN_LIFETIME) / (float)TOKEN_LIFETIME;
|
|
|
- uint8_t barWidth = (uint8_t)((float)(SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1)) * percentDone);
|
|
|
- uint8_t barX =
|
|
|
- ((SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1) - barWidth) >> 1) + PROGRESS_BAR_MARGIN;
|
|
|
-
|
|
|
canvas_draw_box(
|
|
|
canvas,
|
|
|
- barX,
|
|
|
+ scene_state->progress_bar_x,
|
|
|
SCREEN_HEIGHT - PROGRESS_BAR_MARGIN - PROGRESS_BAR_HEIGHT,
|
|
|
- barWidth,
|
|
|
+ scene_state->progress_bar_width,
|
|
|
PROGRESS_BAR_HEIGHT);
|
|
|
|
|
|
if(plugin_state->tokens_count > 1) {
|
|
|
@@ -493,6 +433,8 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) {
|
|
|
if(plugin_state->current_scene_state == NULL) return;
|
|
|
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
|
|
|
|
|
|
+ totp_generate_code_worker_stop(scene_state->generate_code_worker_context);
|
|
|
+
|
|
|
if(plugin_state->automation_method & AutomationMethodBadUsb) {
|
|
|
totp_usb_type_code_worker_stop(scene_state->usb_type_code_worker_context);
|
|
|
}
|
|
|
@@ -506,8 +448,8 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) {
|
|
|
free(scene_state->notification_sequence_new_token);
|
|
|
}
|
|
|
|
|
|
- if(scene_state->notification_sequence_badusb != NULL) {
|
|
|
- free(scene_state->notification_sequence_badusb);
|
|
|
+ if(scene_state->notification_sequence_automation != NULL) {
|
|
|
+ free(scene_state->notification_sequence_automation);
|
|
|
}
|
|
|
|
|
|
furi_mutex_free(scene_state->last_code_update_sync);
|