MX
2023-04-13 21:20:29 +03:00
parent 6b70e37ae3
commit c7637a0fda
41 changed files with 505 additions and 341 deletions

View File

@@ -1,6 +1,5 @@
#include "totp_input_text.h"
#include <gui/view_i.h>
#include "../../../lib/polyfills/strnlen.h"
void view_draw(View* view, Canvas* canvas) {
furi_assert(view);

View File

@@ -6,6 +6,8 @@
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
#define INPUT_BUFFER_SIZE (255)
typedef struct {
char* user_input;
size_t user_input_length;
@@ -20,8 +22,6 @@ typedef struct {
void* callback_data;
} InputTextSceneContext;
#define INPUT_BUFFER_SIZE 255
typedef struct {
TextInput* text_input;
View* text_input_view;

View File

@@ -44,10 +44,6 @@ typedef struct {
FuriString* duration_text;
} SceneState;
void totp_scene_add_new_token_init(const PluginState* plugin_state) {
UNUSED(plugin_state);
}
static void on_token_name_user_comitted(InputTextSceneCallbackResult* result) {
SceneState* scene_state = result->callback_data;
free(scene_state->token_name);
@@ -354,7 +350,3 @@ void totp_scene_add_new_token_deactivate(PluginState* plugin_state) {
free(plugin_state->current_scene_state);
plugin_state->current_scene_state = NULL;
}
void totp_scene_add_new_token_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@@ -1,8 +1,6 @@
#pragma once
#include <gui/gui.h>
#include <furi.h>
#include <furi_hal.h>
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
@@ -10,11 +8,9 @@ typedef struct {
uint16_t current_token_index;
} TokenAddEditSceneContext;
void totp_scene_add_new_token_init(const PluginState* plugin_state);
void totp_scene_add_new_token_activate(
PluginState* plugin_state,
const TokenAddEditSceneContext* context);
void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state);
bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state);
void totp_scene_add_new_token_deactivate(PluginState* plugin_state);
void totp_scene_add_new_token_free(const PluginState* plugin_state);

View File

@@ -44,10 +44,6 @@ typedef struct {
Control selected_control;
} SceneState;
void totp_scene_app_settings_init(const PluginState* plugin_state) {
UNUSED(plugin_state);
}
void totp_scene_app_settings_activate(
PluginState* plugin_state,
const AppSettingsSceneContext* context) {
@@ -332,7 +328,3 @@ void totp_scene_app_settings_deactivate(PluginState* plugin_state) {
free(plugin_state->current_scene_state);
plugin_state->current_scene_state = NULL;
}
void totp_scene_app_settings_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@@ -8,7 +8,6 @@ typedef struct {
uint16_t current_token_index;
} AppSettingsSceneContext;
void totp_scene_app_settings_init(const PluginState* plugin_state);
void totp_scene_app_settings_activate(
PluginState* plugin_state,
const AppSettingsSceneContext* context);
@@ -16,5 +15,4 @@ void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plu
bool totp_scene_app_settings_handle_event(
const PluginEvent* const event,
PluginState* plugin_state);
void totp_scene_app_settings_deactivate(PluginState* plugin_state);
void totp_scene_app_settings_free(const PluginState* plugin_state);
void totp_scene_app_settings_deactivate(PluginState* plugin_state);

View File

@@ -18,10 +18,6 @@ typedef struct {
uint8_t code_length;
} SceneState;
void totp_scene_authenticate_init(PluginState* plugin_state) {
memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE);
}
void totp_scene_authenticate_activate(PluginState* plugin_state) {
SceneState* scene_state = malloc(sizeof(SceneState));
furi_check(scene_state != NULL);
@@ -162,7 +158,3 @@ void totp_scene_authenticate_deactivate(PluginState* plugin_state) {
free(plugin_state->current_scene_state);
plugin_state->current_scene_state = NULL;
}
void totp_scene_authenticate_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@@ -4,11 +4,9 @@
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
void totp_scene_authenticate_init(PluginState* plugin_state);
void totp_scene_authenticate_activate(PluginState* plugin_state);
void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state);
bool totp_scene_authenticate_handle_event(
const PluginEvent* const event,
PluginState* plugin_state);
void totp_scene_authenticate_deactivate(PluginState* plugin_state);
void totp_scene_authenticate_free(const PluginState* plugin_state);

View File

@@ -2,39 +2,44 @@
#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"
#endif
#include "../../fonts/mode-nine/mode_nine.h"
static const char* STEAM_ALGO_ALPHABET = "23456789BCDFGHJKMNPQRTVWXY";
static const uint8_t PROGRESS_BAR_MARGIN = 3;
static const uint8_t PROGRESS_BAR_HEIGHT = 4;
#define PROGRESS_BAR_MARGIN (3)
#define PROGRESS_BAR_HEIGHT (4)
typedef struct {
uint8_t progress_bar_x;
uint8_t progress_bar_width;
uint8_t code_total_length;
uint8_t code_offset_x;
uint8_t code_offset_x_inc;
uint8_t code_offset_y;
} UiPrecalculatedDimensions;
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;
UiPrecalculatedDimensions ui_precalculated_dimensions;
} SceneState;
static const NotificationSequence*
@@ -80,7 +85,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,110 +96,100 @@ 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);
}
}
static void draw_totp_code(Canvas* const canvas, const SceneState* const scene_state) {
uint8_t code_length = scene_state->current_token->digits;
uint8_t offset_x = scene_state->ui_precalculated_dimensions.code_offset_x;
uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width;
uint8_t total_length = code_length * (char_width + modeNine_15ptFontInfo.spacePixels);
uint8_t offset_x = (SCREEN_WIDTH - total_length) >> 1;
uint8_t offset_y = SCREEN_HEIGHT_CENTER - (modeNine_15ptFontInfo.height >> 1);
uint8_t offset_x_inc = scene_state->ui_precalculated_dimensions.code_offset_x_inc;
for(uint8_t i = 0; i < code_length; i++) {
char ch = scene_state->last_code[i];
uint8_t char_index = ch - modeNine_15ptFontInfo.startChar;
canvas_draw_xbm(
canvas,
offset_x,
offset_y,
char_width,
modeNine_15ptFontInfo.height,
&modeNine_15ptFontInfo.data[modeNine_15ptFontInfo.charInfo[char_index].offset]);
if(ch >= modeNine_15ptFontInfo.startChar && ch <= modeNine_15ptFontInfo.endChar) {
uint8_t char_index = ch - modeNine_15ptFontInfo.startChar;
canvas_draw_xbm(
canvas,
offset_x,
scene_state->ui_precalculated_dimensions.code_offset_y,
char_width,
modeNine_15ptFontInfo.height,
&modeNine_15ptFontInfo.data[modeNine_15ptFontInfo.charInfo[char_index].offset]);
}
offset_x += char_width + modeNine_15ptFontInfo.spacePixels;
offset_x += offset_x_inc;
}
}
void totp_scene_generate_token_init(const PluginState* plugin_state) {
UNUSED(plugin_state);
static void on_new_token_code_generated(bool time_left, void* context) {
const PluginState* plugin_state = context;
SceneState* scene_state = plugin_state->current_scene_state;
uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width;
scene_state->ui_precalculated_dimensions.code_total_length =
scene_state->current_token->digits * (char_width + modeNine_15ptFontInfo.spacePixels);
scene_state->ui_precalculated_dimensions.code_offset_x =
(SCREEN_WIDTH - scene_state->ui_precalculated_dimensions.code_total_length) >> 1;
scene_state->ui_precalculated_dimensions.code_offset_x_inc =
char_width + modeNine_15ptFontInfo.spacePixels;
scene_state->ui_precalculated_dimensions.code_offset_y =
SCREEN_HEIGHT_CENTER - (modeNine_15ptFontInfo.height >> 1);
if(time_left) {
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->ui_precalculated_dimensions.progress_bar_width =
(uint8_t)((float)(SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1)) * code_lifetime_percent);
scene_state->ui_precalculated_dimensions.progress_bar_x =
((SCREEN_WIDTH - (PROGRESS_BAR_MARGIN << 1) -
scene_state->ui_precalculated_dimensions.progress_bar_width) >>
1) +
PROGRESS_BAR_MARGIN;
}
void totp_scene_generate_token_activate(
@@ -234,15 +229,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);
}
@@ -255,11 +249,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) {
@@ -281,54 +292,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);
@@ -356,17 +320,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->ui_precalculated_dimensions.progress_bar_x,
SCREEN_HEIGHT - PROGRESS_BAR_MARGIN - PROGRESS_BAR_HEIGHT,
barWidth,
scene_state->ui_precalculated_dimensions.progress_bar_width,
PROGRESS_BAR_HEIGHT);
if(plugin_state->tokens_count > 1) {
@@ -496,6 +454,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);
}
@@ -509,8 +469,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);
@@ -518,7 +478,3 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) {
free(scene_state);
plugin_state->current_scene_state = NULL;
}
void totp_scene_generate_token_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@@ -8,7 +8,6 @@ typedef struct {
uint16_t current_token_index;
} GenerateTokenSceneContext;
void totp_scene_generate_token_init(const PluginState* plugin_state);
void totp_scene_generate_token_activate(
PluginState* plugin_state,
const GenerateTokenSceneContext* context);
@@ -17,4 +16,3 @@ bool totp_scene_generate_token_handle_event(
const PluginEvent* const event,
PluginState* plugin_state);
void totp_scene_generate_token_deactivate(PluginState* plugin_state);
void totp_scene_generate_token_free(const PluginState* plugin_state);

View File

@@ -24,10 +24,6 @@ typedef struct {
TotpNullable_uint16_t current_token_index;
} SceneState;
void totp_scene_token_menu_init(const PluginState* plugin_state) {
UNUSED(plugin_state);
}
void totp_scene_token_menu_activate(
PluginState* plugin_state,
const TokenMenuSceneContext* context) {
@@ -204,7 +200,3 @@ void totp_scene_token_menu_deactivate(PluginState* plugin_state) {
free(plugin_state->current_scene_state);
plugin_state->current_scene_state = NULL;
}
void totp_scene_token_menu_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@@ -8,11 +8,9 @@ typedef struct {
uint16_t current_token_index;
} TokenMenuSceneContext;
void totp_scene_token_menu_init(const PluginState* plugin_state);
void totp_scene_token_menu_activate(
PluginState* plugin_state,
const TokenMenuSceneContext* context);
void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state);
bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state);
void totp_scene_token_menu_deactivate(PluginState* plugin_state);
void totp_scene_token_menu_free(const PluginState* plugin_state);