update totp

This commit is contained in:
MX 2022-11-10 08:32:21 +03:00
parent 3420cda83a
commit ef72ad2462
No known key found for this signature in database
GPG Key ID: 6C4C311DFD4B4AB5
49 changed files with 921 additions and 1099 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

View File

@ -2,6 +2,16 @@
#include <gui/view_i.h>
#include "../../types/common.h"
size_t strnlen(const char* s, size_t maxlen) {
size_t len;
for(len = 0; len < maxlen; len++, s++) {
if(!*s) break;
}
return len;
}
void view_draw(View* view, Canvas* canvas) {
furi_assert(view);
if(view->draw_callback) {
@ -32,16 +42,23 @@ static void commit_text_input_callback(void* context) {
InputTextSceneState* text_input_state = (InputTextSceneState*)context;
if(text_input_state->callback != 0) {
InputTextSceneCallbackResult* result = malloc(sizeof(InputTextSceneCallbackResult));
result->user_input_length = strlen(text_input_state->text_input_buffer);
furi_check(result != NULL);
result->user_input_length =
strnlen(text_input_state->text_input_buffer, INPUT_BUFFER_SIZE);
result->user_input = malloc(result->user_input_length + 1);
furi_check(result->user_input != NULL);
result->callback_data = text_input_state->callback_data;
strcpy(result->user_input, text_input_state->text_input_buffer);
strlcpy(
result->user_input,
text_input_state->text_input_buffer,
result->user_input_length + 1);
text_input_state->callback(result);
}
}
InputTextSceneState* totp_input_text_activate(InputTextSceneContext* context) {
InputTextSceneState* text_input_state = malloc(sizeof(InputTextSceneState));
furi_check(text_input_state != NULL);
text_input_state->text_input = text_input_alloc();
text_input_state->text_input_view = text_input_get_view(text_input_state->text_input);
text_input_state->callback = context->callback;

View File

@ -10,7 +10,7 @@
typedef struct {
char* user_input;
uint8_t user_input_length;
size_t user_input_length;
void* callback_data;
} InputTextSceneCallbackResult;

View File

@ -8,6 +8,8 @@
#include "../../services/base32/base32.h"
#include "../../services/config/config.h"
#include "../../services/ui/ui_controls.h"
#include "../../services/roll_value/roll_value.h"
#include "../../services/nullable/nullable.h"
#include "../generate_token/totp_scene_generate_token.h"
#define TOKEN_ALGO_LIST_LENGTH 3
@ -25,22 +27,22 @@ typedef enum {
typedef struct {
char* token_name;
uint8_t token_name_length;
size_t token_name_length;
char* token_secret;
uint8_t token_secret_length;
size_t token_secret_length;
bool saved;
Control selected_control;
InputTextSceneContext* token_name_input_context;
InputTextSceneContext* token_secret_input_context;
InputTextSceneState* input_state;
uint32_t input_started_at;
int16_t current_token_index;
int32_t screen_y_offset;
TotpNullable_uint16_t current_token_index;
int16_t screen_y_offset;
TokenHashAlgo algo;
TokenDigitsCount digits_count;
} SceneState;
void totp_scene_add_new_token_init(PluginState* plugin_state) {
void totp_scene_add_new_token_init(const PluginState* plugin_state) {
UNUSED(plugin_state);
}
@ -66,6 +68,7 @@ void totp_scene_add_new_token_activate(
PluginState* plugin_state,
const TokenAddEditSceneContext* context) {
SceneState* scene_state = malloc(sizeof(SceneState));
furi_check(scene_state != NULL);
plugin_state->current_scene_state = scene_state;
scene_state->token_name = "Name";
scene_state->token_name_length = strlen(scene_state->token_name);
@ -73,11 +76,13 @@ void totp_scene_add_new_token_activate(
scene_state->token_secret_length = strlen(scene_state->token_secret);
scene_state->token_name_input_context = malloc(sizeof(InputTextSceneContext));
furi_check(scene_state->token_name_input_context != NULL);
scene_state->token_name_input_context->header_text = "Enter token name";
scene_state->token_name_input_context->callback_data = scene_state;
scene_state->token_name_input_context->callback = on_token_name_user_comitted;
scene_state->token_secret_input_context = malloc(sizeof(InputTextSceneContext));
furi_check(scene_state->token_secret_input_context != NULL);
scene_state->token_secret_input_context->header_text = "Enter token secret";
scene_state->token_secret_input_context->callback_data = scene_state;
scene_state->token_secret_input_context->callback = on_token_secret_user_comitted;
@ -87,9 +92,9 @@ void totp_scene_add_new_token_activate(
scene_state->input_state = NULL;
if(context == NULL) {
scene_state->current_token_index = -1;
TOTP_NULLABLE_NULL(scene_state->current_token_index);
} else {
scene_state->current_token_index = context->current_token_index;
TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index);
}
}
@ -150,143 +155,151 @@ void update_screen_y_offset(SceneState* scene_state) {
}
bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state) {
if(event->type == EventTypeKey) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(scene_state->input_started_at > 0 &&
furi_get_tick() - scene_state->input_started_at > 300) {
return totp_input_text_handle_event(event, scene_state->input_state);
}
if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) {
return false;
} else if(event->input.type == InputTypePress) {
switch(event->input.key) {
case InputKeyUp:
if(scene_state->selected_control > TokenNameTextBox) {
scene_state->selected_control--;
update_screen_y_offset(scene_state);
}
break;
case InputKeyDown:
if(scene_state->selected_control < ConfirmButton) {
scene_state->selected_control++;
update_screen_y_offset(scene_state);
}
break;
case InputKeyRight:
if(scene_state->selected_control == TokenAlgoSelect) {
if(scene_state->algo < SHA512) {
scene_state->algo++;
} else {
scene_state->algo = SHA1;
}
} else if(scene_state->selected_control == TokenLengthSelect) {
if(scene_state->digits_count < TOTP_8_DIGITS) {
scene_state->digits_count++;
} else {
scene_state->digits_count = TOTP_6_DIGITS;
}
}
break;
case InputKeyLeft:
if(scene_state->selected_control == TokenAlgoSelect) {
if(scene_state->algo > SHA1) {
scene_state->algo--;
} else {
scene_state->algo = SHA512;
}
} else if(scene_state->selected_control == TokenLengthSelect) {
if(scene_state->digits_count > TOTP_6_DIGITS) {
scene_state->digits_count--;
} else {
scene_state->digits_count = TOTP_8_DIGITS;
}
}
break;
case InputKeyOk:
switch(scene_state->selected_control) {
case TokenNameTextBox:
if(scene_state->input_state != NULL) {
totp_input_text_free(scene_state->input_state);
}
scene_state->input_state =
totp_input_text_activate(scene_state->token_name_input_context);
scene_state->input_started_at = furi_get_tick();
break;
case TokenSecretTextBox:
if(scene_state->input_state != NULL) {
totp_input_text_free(scene_state->input_state);
}
scene_state->input_state =
totp_input_text_activate(scene_state->token_secret_input_context);
scene_state->input_started_at = furi_get_tick();
break;
case TokenAlgoSelect:
break;
case TokenLengthSelect:
break;
case ConfirmButton: {
TokenInfo* tokenInfo = token_info_alloc();
bool token_secret_set = token_info_set_secret(
tokenInfo,
scene_state->token_secret,
scene_state->token_secret_length,
&plugin_state->iv[0]);
if(token_secret_set) {
tokenInfo->name = malloc(scene_state->token_name_length + 1);
strcpy(tokenInfo->name, scene_state->token_name);
tokenInfo->algo = scene_state->algo;
tokenInfo->digits = scene_state->digits_count;
if(plugin_state->tokens_list == NULL) {
plugin_state->tokens_list = list_init_head(tokenInfo);
} else {
list_add(plugin_state->tokens_list, tokenInfo);
}
plugin_state->tokens_count++;
totp_config_file_save_new_token(tokenInfo);
GenerateTokenSceneContext generate_scene_context = {
.current_token_index = plugin_state->tokens_count - 1};
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, &generate_scene_context);
} else {
token_info_free(tokenInfo);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "Back", NULL, NULL);
dialog_message_set_text(
message,
"Token secret is invalid",
SCREEN_WIDTH_CENTER,
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
dialog_message_show(plugin_state->dialogs, message);
dialog_message_free(message);
scene_state->selected_control = TokenSecretTextBox;
update_screen_y_offset(scene_state);
}
break;
}
}
break;
case InputKeyBack:
if(scene_state->current_token_index >= 0) {
GenerateTokenSceneContext generate_scene_context = {
.current_token_index = scene_state->current_token_index};
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, &generate_scene_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
break;
default:
break;
}
}
if(event->type != EventTypeKey) {
return true;
}
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(scene_state->input_started_at > 0 &&
furi_get_tick() - scene_state->input_started_at > 300) {
return totp_input_text_handle_event(event, scene_state->input_state);
}
if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) {
return false;
}
if(event->input.type != InputTypePress) {
return true;
}
switch(event->input.key) {
case InputKeyUp:
totp_roll_value_uint8_t(
&scene_state->selected_control,
-1,
TokenNameTextBox,
ConfirmButton,
RollOverflowBehaviorStop);
update_screen_y_offset(scene_state);
break;
case InputKeyDown:
totp_roll_value_uint8_t(
&scene_state->selected_control,
1,
TokenNameTextBox,
ConfirmButton,
RollOverflowBehaviorStop);
update_screen_y_offset(scene_state);
break;
case InputKeyRight:
if(scene_state->selected_control == TokenAlgoSelect) {
totp_roll_value_uint8_t(&scene_state->algo, 1, SHA1, SHA512, RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == TokenLengthSelect) {
totp_roll_value_uint8_t(
&scene_state->digits_count,
1,
TOTP_6_DIGITS,
TOTP_8_DIGITS,
RollOverflowBehaviorRoll);
}
break;
case InputKeyLeft:
if(scene_state->selected_control == TokenAlgoSelect) {
totp_roll_value_uint8_t(
&scene_state->algo, -1, SHA1, SHA512, RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == TokenLengthSelect) {
totp_roll_value_uint8_t(
&scene_state->digits_count,
-1,
TOTP_6_DIGITS,
TOTP_8_DIGITS,
RollOverflowBehaviorRoll);
}
break;
case InputKeyOk:
switch(scene_state->selected_control) {
case TokenNameTextBox:
if(scene_state->input_state != NULL) {
totp_input_text_free(scene_state->input_state);
}
scene_state->input_state =
totp_input_text_activate(scene_state->token_name_input_context);
scene_state->input_started_at = furi_get_tick();
break;
case TokenSecretTextBox:
if(scene_state->input_state != NULL) {
totp_input_text_free(scene_state->input_state);
}
scene_state->input_state =
totp_input_text_activate(scene_state->token_secret_input_context);
scene_state->input_started_at = furi_get_tick();
break;
case TokenAlgoSelect:
break;
case TokenLengthSelect:
break;
case ConfirmButton: {
TokenInfo* tokenInfo = token_info_alloc();
bool token_secret_set = token_info_set_secret(
tokenInfo,
scene_state->token_secret,
scene_state->token_secret_length,
&plugin_state->iv[0]);
if(token_secret_set) {
tokenInfo->name = malloc(scene_state->token_name_length + 1);
furi_check(tokenInfo->name != NULL);
strlcpy(
tokenInfo->name, scene_state->token_name, scene_state->token_name_length + 1);
tokenInfo->algo = scene_state->algo;
tokenInfo->digits = scene_state->digits_count;
TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check);
plugin_state->tokens_count++;
totp_config_file_save_new_token(tokenInfo);
GenerateTokenSceneContext generate_scene_context = {
.current_token_index = plugin_state->tokens_count - 1};
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, &generate_scene_context);
} else {
token_info_free(tokenInfo);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "Back", NULL, NULL);
dialog_message_set_text(
message,
"Token secret is invalid",
SCREEN_WIDTH_CENTER,
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
dialog_message_show(plugin_state->dialogs, message);
dialog_message_free(message);
scene_state->selected_control = TokenSecretTextBox;
update_screen_y_offset(scene_state);
}
break;
}
default:
break;
}
break;
case InputKeyBack:
if(!scene_state->current_token_index.is_null) {
GenerateTokenSceneContext generate_scene_context = {
.current_token_index = scene_state->current_token_index.value};
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, &generate_scene_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
break;
default:
break;
}
return true;
}
@ -310,6 +323,6 @@ void totp_scene_add_new_token_deactivate(PluginState* plugin_state) {
plugin_state->current_scene_state = NULL;
}
void totp_scene_add_new_token_free(PluginState* plugin_state) {
void totp_scene_add_new_token_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@ -7,14 +7,14 @@
#include "../../types/plugin_event.h"
typedef struct {
uint8_t current_token_index;
uint16_t current_token_index;
} TokenAddEditSceneContext;
void totp_scene_add_new_token_init(PluginState* plugin_state);
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(PluginState* plugin_state);
void totp_scene_add_new_token_free(const PluginState* plugin_state);

View File

@ -4,6 +4,8 @@
#include "../token_menu/totp_scene_token_menu.h"
#include "../../services/ui/constants.h"
#include "../../services/config/config.h"
#include "../../services/roll_value/roll_value.h"
#include "../../services/nullable/nullable.h"
#define DIGIT_TO_CHAR(digit) ((digit) + '0')
@ -12,11 +14,11 @@ typedef enum { HoursInput, MinutesInput, ConfirmButton } Control;
typedef struct {
int8_t tz_offset_hours;
uint8_t tz_offset_minutes;
int16_t current_token_index;
TotpNullable_uint16_t current_token_index;
Control selected_control;
} SceneState;
void totp_scene_app_settings_init(PluginState* plugin_state) {
void totp_scene_app_settings_init(const PluginState* plugin_state) {
UNUSED(plugin_state);
}
@ -24,11 +26,12 @@ void totp_scene_app_settings_activate(
PluginState* plugin_state,
const AppSettingsSceneContext* context) {
SceneState* scene_state = malloc(sizeof(SceneState));
furi_check(scene_state != NULL);
plugin_state->current_scene_state = scene_state;
if(context != NULL) {
scene_state->current_token_index = context->current_token_index;
TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index);
} else {
scene_state->current_token_index = -1;
TOTP_NULLABLE_NULL(scene_state->current_token_index);
}
float off_int;
@ -53,7 +56,7 @@ static void two_digit_to_str(int8_t num, char* str) {
}
void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Timezone offset");
@ -90,79 +93,80 @@ void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_st
scene_state->selected_control == ConfirmButton);
}
bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState* plugin_state) {
if(event->type == EventTypeKey) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(event->input.type == InputTypePress) {
switch(event->input.key) {
case InputKeyUp:
if(scene_state->selected_control > HoursInput) {
scene_state->selected_control--;
}
break;
case InputKeyDown:
if(scene_state->selected_control < ConfirmButton) {
scene_state->selected_control++;
}
break;
case InputKeyRight:
if(scene_state->selected_control == HoursInput) {
if(scene_state->tz_offset_hours < 12) {
scene_state->tz_offset_hours++;
}
} else if(scene_state->selected_control == MinutesInput) {
if(scene_state->tz_offset_minutes < 45) {
scene_state->tz_offset_minutes += 15;
} else {
scene_state->tz_offset_minutes = 0;
}
}
break;
case InputKeyLeft:
if(scene_state->selected_control == HoursInput) {
if(scene_state->tz_offset_hours > -12) {
scene_state->tz_offset_hours--;
}
} else if(scene_state->selected_control == MinutesInput) {
if(scene_state->tz_offset_minutes >= 15) {
scene_state->tz_offset_minutes -= 15;
} else {
scene_state->tz_offset_minutes = 45;
}
}
break;
case InputKeyOk:
if(scene_state->selected_control == ConfirmButton) {
plugin_state->timezone_offset = (float)scene_state->tz_offset_hours +
(float)scene_state->tz_offset_minutes / 60.0f;
totp_config_file_update_timezone_offset(plugin_state->timezone_offset);
bool totp_scene_app_settings_handle_event(
const PluginEvent* const event,
PluginState* plugin_state) {
if(event->type != EventTypeKey) {
return true;
}
if(scene_state->current_token_index >= 0) {
TokenMenuSceneContext generate_scene_context = {
.current_token_index = scene_state->current_token_index};
totp_scene_director_activate_scene(
plugin_state, TotpSceneTokenMenu, &generate_scene_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL);
}
}
break;
case InputKeyBack: {
if(scene_state->current_token_index >= 0) {
TokenMenuSceneContext generate_scene_context = {
.current_token_index = scene_state->current_token_index};
totp_scene_director_activate_scene(
plugin_state, TotpSceneTokenMenu, &generate_scene_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL);
}
break;
}
default:
break;
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(event->input.type != InputTypePress) {
return true;
}
switch(event->input.key) {
case InputKeyUp:
totp_roll_value_uint8_t(
&scene_state->selected_control,
-1,
HoursInput,
ConfirmButton,
RollOverflowBehaviorStop);
break;
case InputKeyDown:
totp_roll_value_uint8_t(
&scene_state->selected_control, 1, HoursInput, ConfirmButton, RollOverflowBehaviorStop);
break;
case InputKeyRight:
if(scene_state->selected_control == HoursInput) {
totp_roll_value_int8_t(
&scene_state->tz_offset_hours, 1, -12, 12, RollOverflowBehaviorStop);
} else if(scene_state->selected_control == MinutesInput) {
totp_roll_value_uint8_t(
&scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll);
}
break;
case InputKeyLeft:
if(scene_state->selected_control == HoursInput) {
totp_roll_value_int8_t(
&scene_state->tz_offset_hours, -1, -12, 12, RollOverflowBehaviorStop);
} else if(scene_state->selected_control == MinutesInput) {
totp_roll_value_uint8_t(
&scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll);
}
break;
case InputKeyOk:
if(scene_state->selected_control == ConfirmButton) {
plugin_state->timezone_offset = (float)scene_state->tz_offset_hours +
(float)scene_state->tz_offset_minutes / 60.0f;
totp_config_file_update_timezone_offset(plugin_state->timezone_offset);
if(!scene_state->current_token_index.is_null) {
TokenMenuSceneContext generate_scene_context = {
.current_token_index = scene_state->current_token_index.value};
totp_scene_director_activate_scene(
plugin_state, TotpSceneTokenMenu, &generate_scene_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL);
}
}
break;
case InputKeyBack: {
if(!scene_state->current_token_index.is_null) {
TokenMenuSceneContext generate_scene_context = {
.current_token_index = scene_state->current_token_index.value};
totp_scene_director_activate_scene(
plugin_state, TotpSceneTokenMenu, &generate_scene_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL);
}
break;
}
default:
break;
}
return true;
}
@ -173,6 +177,6 @@ void totp_scene_app_settings_deactivate(PluginState* plugin_state) {
plugin_state->current_scene_state = NULL;
}
void totp_scene_app_settings_free(PluginState* plugin_state) {
void totp_scene_app_settings_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@ -7,14 +7,16 @@
#include "../../types/plugin_event.h"
typedef struct {
uint8_t current_token_index;
uint16_t current_token_index;
} AppSettingsSceneContext;
void totp_scene_app_settings_init(PluginState* plugin_state);
void totp_scene_app_settings_init(const PluginState* plugin_state);
void totp_scene_app_settings_activate(
PluginState* plugin_state,
const AppSettingsSceneContext* context);
void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state);
bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState* plugin_state);
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(PluginState* plugin_state);
void totp_scene_app_settings_free(const PluginState* plugin_state);

View File

@ -1,7 +1,7 @@
#include "totp_scene_authenticate.h"
#include <dialogs/dialogs.h>
#include <totp_icons.h>
#include "../../types/common.h"
#include "../../services/ui/icons.h"
#include "../../services/ui/constants.h"
#include "../../services/config/config.h"
#include "../scene_director.h"
@ -9,6 +9,10 @@
#include "../../services/crypto/crypto.h"
#define MAX_CODE_LENGTH TOTP_IV_SIZE
#define ARROW_UP_CODE 2
#define ARROW_RIGHT_CODE 8
#define ARROW_DOWN_CODE 11
#define ARROW_LEFT_CODE 5
typedef struct {
uint8_t code_input[MAX_CODE_LENGTH];
@ -21,6 +25,7 @@ void totp_scene_authenticate_init(PluginState* plugin_state) {
void totp_scene_authenticate_activate(PluginState* plugin_state) {
SceneState* scene_state = malloc(sizeof(SceneState));
furi_check(scene_state != NULL);
scene_state->code_length = 0;
memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH);
plugin_state->current_scene_state = scene_state;
@ -28,7 +33,7 @@ void totp_scene_authenticate_activate(PluginState* plugin_state) {
}
void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
int v_shift = 0;
if(scene_state->code_length > 0) {
@ -62,7 +67,7 @@ void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_st
const uint8_t PIN_ASTERISK_RADIUS = 3;
const uint8_t PIN_ASTERISK_STEP = (PIN_ASTERISK_RADIUS << 1) + 2;
if(scene_state->code_length > 0) {
uint8_t left_start_x = (scene_state->code_length - 1) * PIN_ASTERISK_STEP >> 1;
uint8_t left_start_x = ((scene_state->code_length - 1) * PIN_ASTERISK_STEP) >> 1;
for(uint8_t i = 0; i < scene_state->code_length; i++) {
canvas_draw_disc(
canvas,
@ -73,80 +78,82 @@ void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_st
}
}
bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState* plugin_state) {
if(event->type == EventTypeKey) {
if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) {
return false;
} else if(event->input.type == InputTypePress) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
bool totp_scene_authenticate_handle_event(
const PluginEvent* const event,
PluginState* plugin_state) {
if(event->type != EventTypeKey) {
return true;
}
const uint8_t ARROW_UP_CODE = 2;
const uint8_t ARROW_RIGHT_CODE = 8;
const uint8_t ARROW_DOWN_CODE = 11;
const uint8_t ARROW_LEFT_CODE = 5;
if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) {
return false;
}
switch(event->input.key) {
case InputKeyUp:
if(scene_state->code_length < MAX_CODE_LENGTH) {
scene_state->code_input[scene_state->code_length] = ARROW_UP_CODE;
scene_state->code_length++;
}
break;
case InputKeyDown:
if(scene_state->code_length < MAX_CODE_LENGTH) {
scene_state->code_input[scene_state->code_length] = ARROW_DOWN_CODE;
scene_state->code_length++;
}
break;
case InputKeyRight:
if(scene_state->code_length < MAX_CODE_LENGTH) {
scene_state->code_input[scene_state->code_length] = ARROW_RIGHT_CODE;
scene_state->code_length++;
}
break;
case InputKeyLeft:
if(scene_state->code_length < MAX_CODE_LENGTH) {
scene_state->code_input[scene_state->code_length] = ARROW_LEFT_CODE;
scene_state->code_length++;
}
break;
case InputKeyOk:
totp_crypto_seed_iv(
plugin_state, &scene_state->code_input[0], scene_state->code_length);
if(event->input.type != InputTypePress) {
return true;
}
if(totp_crypto_verify_key(plugin_state)) {
FURI_LOG_D(LOGGING_TAG, "PIN is valid");
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
} else {
FURI_LOG_D(LOGGING_TAG, "PIN is NOT valid");
memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH);
memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE);
scene_state->code_length = 0;
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "Try again", NULL, NULL);
dialog_message_set_header(
message,
"You entered\ninvalid PIN",
SCREEN_WIDTH_CENTER - 25,
SCREEN_HEIGHT_CENTER - 5,
AlignCenter,
AlignCenter);
dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17);
dialog_message_show(plugin_state->dialogs, message);
dialog_message_free(message);
}
break;
case InputKeyBack:
if(scene_state->code_length > 0) {
scene_state->code_input[scene_state->code_length - 1] = 0;
scene_state->code_length--;
}
break;
default:
break;
}
switch(event->input.key) {
case InputKeyUp:
if(scene_state->code_length < MAX_CODE_LENGTH) {
scene_state->code_input[scene_state->code_length] = ARROW_UP_CODE;
scene_state->code_length++;
}
break;
case InputKeyDown:
if(scene_state->code_length < MAX_CODE_LENGTH) {
scene_state->code_input[scene_state->code_length] = ARROW_DOWN_CODE;
scene_state->code_length++;
}
break;
case InputKeyRight:
if(scene_state->code_length < MAX_CODE_LENGTH) {
scene_state->code_input[scene_state->code_length] = ARROW_RIGHT_CODE;
scene_state->code_length++;
}
break;
case InputKeyLeft:
if(scene_state->code_length < MAX_CODE_LENGTH) {
scene_state->code_input[scene_state->code_length] = ARROW_LEFT_CODE;
scene_state->code_length++;
}
break;
case InputKeyOk:
totp_crypto_seed_iv(plugin_state, &scene_state->code_input[0], scene_state->code_length);
if(totp_crypto_verify_key(plugin_state)) {
FURI_LOG_D(LOGGING_TAG, "PIN is valid");
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
} else {
FURI_LOG_D(LOGGING_TAG, "PIN is NOT valid");
memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH);
memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE);
scene_state->code_length = 0;
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "Try again", NULL, NULL);
dialog_message_set_header(
message,
"You entered\ninvalid PIN",
SCREEN_WIDTH_CENTER - 25,
SCREEN_HEIGHT_CENTER - 5,
AlignCenter,
AlignCenter);
dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17);
dialog_message_show(plugin_state->dialogs, message);
dialog_message_free(message);
}
break;
case InputKeyBack:
if(scene_state->code_length > 0) {
scene_state->code_input[scene_state->code_length - 1] = 0;
scene_state->code_length--;
}
break;
default:
break;
}
return true;
@ -158,6 +165,6 @@ void totp_scene_authenticate_deactivate(PluginState* plugin_state) {
plugin_state->current_scene_state = NULL;
}
void totp_scene_authenticate_free(PluginState* plugin_state) {
void totp_scene_authenticate_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@ -9,6 +9,8 @@
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(PluginEvent* const event, 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(PluginState* plugin_state);
void totp_scene_authenticate_free(const PluginState* plugin_state);

View File

@ -1,14 +1,16 @@
#include <gui/gui.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <totp_icons.h>
#include "totp_scene_generate_token.h"
#include "../../types/token_info.h"
#include "../../types/common.h"
#include "../../services/ui/icons.h"
#include "../../services/ui/constants.h"
#include "../../services/totp/totp.h"
#include "../../services/config/config.h"
#include "../../services/crypto/crypto.h"
#include "../../services/crypto/memset_s.h"
#include "../../services/roll_value/roll_value.h"
#include "../scene_director.h"
#include "../token_menu/totp_scene_token_menu.h"
@ -16,7 +18,7 @@
#define DIGIT_TO_CHAR(digit) ((digit) + '0')
typedef struct {
uint8_t current_token_index;
uint16_t current_token_index;
char last_code[9];
char* last_code_name;
bool need_token_update;
@ -35,24 +37,17 @@ static const NotificationSequence sequence_short_vibro_and_sound = {
};
static void i_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount len) {
uint8_t str_token_length = 0;
if(len == TOTP_8_DIGITS) {
str[8] = '\0';
str_token_length = 8;
} else if(len == TOTP_6_DIGITS) {
str[6] = '\0';
str_token_length = 6;
}
if(i_token_code == 0) {
if(len > TOTP_6_DIGITS) {
str[7] = '-';
str[6] = '-';
}
str[5] = '-';
str[4] = '-';
str[3] = '-';
str[2] = '-';
str[1] = '-';
str[0] = '-';
if(i_token_code == OTP_ERROR) {
memset(&str[0], '-', str_token_length);
} else {
if(len == TOTP_8_DIGITS) {
str[7] = DIGIT_TO_CHAR(i_token_code % 10);
@ -78,6 +73,8 @@ TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
return TOTP_ALGO_SHA256;
case SHA512:
return TOTP_ALGO_SHA512;
default:
break;
}
return NULL;
@ -95,7 +92,7 @@ void update_totp_params(PluginState* const plugin_state) {
}
}
void totp_scene_generate_token_init(PluginState* plugin_state) {
void totp_scene_generate_token_init(const PluginState* plugin_state) {
UNUSED(plugin_state);
}
@ -130,6 +127,7 @@ void totp_scene_generate_token_activate(
}
}
SceneState* scene_state = malloc(sizeof(SceneState));
furi_check(scene_state != NULL);
if(context == NULL || context->current_token_index > plugin_state->tokens_count) {
scene_state->current_token_index = 0;
} else {
@ -180,7 +178,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
->data);
if(tokenInfo->token != NULL && tokenInfo->token_length > 0) {
uint8_t key_length;
size_t key_length;
uint8_t* key = totp_crypto_decrypt(
tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
@ -195,7 +193,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
TOKEN_LIFETIME),
scene_state->last_code,
tokenInfo->digits);
memset(key, 0, key_length);
memset_s(key, key_length, 0, key_length);
free(key);
} else {
i_token_to_str(0, scene_state->last_code, tokenInfo->digits);
@ -248,65 +246,63 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
canvas_draw_box(canvas, barX, SCREEN_HEIGHT - BAR_MARGIN - BAR_HEIGHT, barWidth, BAR_HEIGHT);
if(plugin_state->tokens_count > 1) {
canvas_draw_xbm(
canvas,
0,
SCREEN_HEIGHT_CENTER - 24,
ICON_ARROW_LEFT_8x9_WIDTH,
ICON_ARROW_LEFT_8x9_HEIGHT,
&ICON_ARROW_LEFT_8x9[0]);
canvas_draw_xbm(
canvas,
SCREEN_WIDTH - 9,
SCREEN_HEIGHT_CENTER - 24,
ICON_ARROW_RIGHT_8x9_WIDTH,
ICON_ARROW_RIGHT_8x9_HEIGHT,
&ICON_ARROW_RIGHT_8x9[0]);
canvas_draw_icon(canvas, 0, SCREEN_HEIGHT_CENTER - 24, &I_totp_arrow_left_8x9);
canvas_draw_icon(
canvas, SCREEN_WIDTH - 9, SCREEN_HEIGHT_CENTER - 24, &I_totp_arrow_right_8x9);
}
}
bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginState* plugin_state) {
if(event->type == EventTypeKey) {
if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) {
return false;
} else if(event->input.type == InputTypePress) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
switch(event->input.key) {
case InputKeyUp:
break;
case InputKeyDown:
break;
case InputKeyRight:
if(scene_state->current_token_index < plugin_state->tokens_count - 1) {
scene_state->current_token_index++;
} else {
scene_state->current_token_index = 0;
}
update_totp_params(plugin_state);
break;
case InputKeyLeft:
if(scene_state->current_token_index > 0) {
scene_state->current_token_index--;
} else {
scene_state->current_token_index = plugin_state->tokens_count - 1;
}
update_totp_params(plugin_state);
break;
case InputKeyOk:
if(plugin_state->tokens_count == 0) {
totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL);
} else {
TokenMenuSceneContext ctx = {
.current_token_index = scene_state->current_token_index};
totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, &ctx);
}
break;
case InputKeyBack:
break;
default:
break;
}
bool totp_scene_generate_token_handle_event(
const PluginEvent* const event,
PluginState* plugin_state) {
if(event->type != EventTypeKey) {
return true;
}
if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) {
return false;
}
if(event->input.type != InputTypePress) {
return true;
}
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
switch(event->input.key) {
case InputKeyUp:
break;
case InputKeyDown:
break;
case InputKeyRight:
totp_roll_value_uint16_t(
&scene_state->current_token_index,
1,
0,
plugin_state->tokens_count - 1,
RollOverflowBehaviorRoll);
update_totp_params(plugin_state);
break;
case InputKeyLeft:
totp_roll_value_uint16_t(
&scene_state->current_token_index,
-1,
0,
plugin_state->tokens_count - 1,
RollOverflowBehaviorRoll);
update_totp_params(plugin_state);
break;
case InputKeyOk:
if(plugin_state->tokens_count == 0) {
totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL);
} else {
TokenMenuSceneContext ctx = {.current_token_index = scene_state->current_token_index};
totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, &ctx);
}
break;
case InputKeyBack:
break;
default:
break;
}
return true;
@ -316,11 +312,10 @@ 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;
free(scene_state->last_code);
free(scene_state);
plugin_state->current_scene_state = NULL;
}
void totp_scene_generate_token_free(PluginState* plugin_state) {
void totp_scene_generate_token_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@ -7,14 +7,16 @@
#include "../../types/plugin_event.h"
typedef struct {
uint8_t current_token_index;
uint16_t current_token_index;
} GenerateTokenSceneContext;
void totp_scene_generate_token_init(PluginState* plugin_state);
void totp_scene_generate_token_init(const PluginState* plugin_state);
void totp_scene_generate_token_activate(
PluginState* plugin_state,
const GenerateTokenSceneContext* context);
void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state);
bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginState* plugin_state);
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(PluginState* plugin_state);
void totp_scene_generate_token_free(const PluginState* plugin_state);

View File

@ -30,6 +30,8 @@ void totp_scene_director_activate_scene(
break;
case TotpSceneNone:
break;
default:
break;
}
plugin_state->current_scene = scene;
@ -55,6 +57,8 @@ void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state
break;
case TotpSceneNone:
break;
default:
break;
}
}
@ -85,10 +89,12 @@ void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_
break;
case TotpSceneNone:
break;
default:
break;
}
}
void totp_scene_director_dispose(PluginState* const plugin_state) {
void totp_scene_director_dispose(const PluginState* const plugin_state) {
totp_scene_generate_token_free(plugin_state);
totp_scene_authenticate_free(plugin_state);
totp_scene_add_new_token_free(plugin_state);
@ -116,6 +122,8 @@ bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* con
break;
case TotpSceneNone:
break;
default:
break;
}
return processing;

View File

@ -12,5 +12,5 @@ void totp_scene_director_activate_scene(
void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state);
void totp_scene_director_init_scenes(PluginState* const plugin_state);
void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state);
void totp_scene_director_dispose(PluginState* const plugin_state);
void totp_scene_director_dispose(const PluginState* const plugin_state);
bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state);

View File

@ -10,6 +10,8 @@
#include "../generate_token/totp_scene_generate_token.h"
#include "../add_new_token/totp_scene_add_new_token.h"
#include "../app_settings/totp_app_settings.h"
#include "../../services/nullable/nullable.h"
#include "../../services/roll_value/roll_value.h"
#define SCREEN_HEIGHT_THIRD (SCREEN_HEIGHT / 3)
#define SCREEN_HEIGHT_THIRD_CENTER (SCREEN_HEIGHT_THIRD >> 1)
@ -18,10 +20,10 @@ typedef enum { AddNewToken, DeleteToken, AppSettings } Control;
typedef struct {
Control selected_control;
int16_t current_token_index;
TotpNullable_uint16_t current_token_index;
} SceneState;
void totp_scene_token_menu_init(PluginState* plugin_state) {
void totp_scene_token_menu_init(const PluginState* plugin_state) {
UNUSED(plugin_state);
}
@ -29,17 +31,18 @@ void totp_scene_token_menu_activate(
PluginState* plugin_state,
const TokenMenuSceneContext* context) {
SceneState* scene_state = malloc(sizeof(SceneState));
furi_check(scene_state != NULL);
plugin_state->current_scene_state = scene_state;
if(context != NULL) {
scene_state->current_token_index = context->current_token_index;
TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index);
} else {
scene_state->current_token_index = -1;
TOTP_NULLABLE_NULL(scene_state->current_token_index);
}
}
void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(scene_state->current_token_index < 0) {
const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(scene_state->current_token_index.is_null) {
ui_control_button_render(
canvas,
SCREEN_WIDTH_CENTER - 36,
@ -84,106 +87,109 @@ void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_stat
}
}
bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* plugin_state) {
if(event->type == EventTypeKey) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(event->input.type == InputTypePress) {
switch(event->input.key) {
case InputKeyUp:
if(scene_state->selected_control > AddNewToken) {
scene_state->selected_control--;
if(scene_state->selected_control == DeleteToken &&
scene_state->current_token_index < 0) {
scene_state->selected_control--;
}
} else {
scene_state->selected_control = AppSettings;
}
break;
case InputKeyDown:
if(scene_state->selected_control < AppSettings) {
scene_state->selected_control++;
if(scene_state->selected_control == DeleteToken &&
scene_state->current_token_index < 0) {
scene_state->selected_control++;
}
} else {
scene_state->selected_control = AddNewToken;
}
break;
case InputKeyRight:
break;
case InputKeyLeft:
break;
case InputKeyOk:
switch(scene_state->selected_control) {
case AddNewToken: {
TokenAddEditSceneContext add_new_token_scene_context = {
.current_token_index = scene_state->current_token_index};
totp_scene_director_activate_scene(
plugin_state, TotpSceneAddNewToken, &add_new_token_scene_context);
break;
}
case DeleteToken: {
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "No", NULL, "Yes");
dialog_message_set_header(message, "Confirmation", 0, 0, AlignLeft, AlignTop);
dialog_message_set_text(
message,
"Are you sure want to delete?",
SCREEN_WIDTH_CENTER,
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
DialogMessageButton dialog_result =
dialog_message_show(plugin_state->dialogs, message);
dialog_message_free(message);
if(dialog_result == DialogMessageButtonRight) {
ListNode* list_node = list_element_at(
plugin_state->tokens_list, scene_state->current_token_index);
TokenInfo* tokenInfo = list_node->data;
token_info_free(tokenInfo);
plugin_state->tokens_list =
list_remove(plugin_state->tokens_list, list_node);
plugin_state->tokens_count--;
totp_full_save_config_file(plugin_state);
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, NULL);
}
break;
}
case AppSettings: {
if(scene_state->current_token_index >= 0) {
AppSettingsSceneContext app_settings_context = {
.current_token_index = scene_state->current_token_index};
totp_scene_director_activate_scene(
plugin_state, TotpSceneAppSettings, &app_settings_context);
} else {
totp_scene_director_activate_scene(
plugin_state, TotpSceneAppSettings, NULL);
}
break;
}
}
break;
case InputKeyBack: {
if(scene_state->current_token_index >= 0) {
GenerateTokenSceneContext generate_scene_context = {
.current_token_index = scene_state->current_token_index};
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, &generate_scene_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
break;
}
default:
break;
}
}
bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state) {
if(event->type != EventTypeKey) {
return true;
}
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(event->input.type != InputTypePress) {
return true;
}
switch(event->input.key) {
case InputKeyUp:
totp_roll_value_uint8_t(
&scene_state->selected_control, -1, AddNewToken, AppSettings, RollOverflowBehaviorRoll);
if(scene_state->selected_control == DeleteToken &&
scene_state->current_token_index.is_null) {
scene_state->selected_control--;
}
break;
case InputKeyDown:
totp_roll_value_uint8_t(
&scene_state->selected_control, 1, AddNewToken, AppSettings, RollOverflowBehaviorRoll);
if(scene_state->selected_control == DeleteToken &&
scene_state->current_token_index.is_null) {
scene_state->selected_control++;
}
break;
case InputKeyRight:
break;
case InputKeyLeft:
break;
case InputKeyOk:
switch(scene_state->selected_control) {
case AddNewToken: {
if(scene_state->current_token_index.is_null) {
totp_scene_director_activate_scene(plugin_state, TotpSceneAddNewToken, NULL);
} else {
TokenAddEditSceneContext add_new_token_scene_context = {
.current_token_index = scene_state->current_token_index.value};
totp_scene_director_activate_scene(
plugin_state, TotpSceneAddNewToken, &add_new_token_scene_context);
}
break;
}
case DeleteToken: {
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "No", NULL, "Yes");
dialog_message_set_header(message, "Confirmation", 0, 0, AlignLeft, AlignTop);
dialog_message_set_text(
message,
"Are you sure want to delete?",
SCREEN_WIDTH_CENTER,
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
DialogMessageButton dialog_result =
dialog_message_show(plugin_state->dialogs, message);
dialog_message_free(message);
if(dialog_result == DialogMessageButtonRight &&
!scene_state->current_token_index.is_null) {
ListNode* list_node = list_element_at(
plugin_state->tokens_list, scene_state->current_token_index.value);
TokenInfo* tokenInfo = list_node->data;
token_info_free(tokenInfo);
plugin_state->tokens_list = list_remove(plugin_state->tokens_list, list_node);
plugin_state->tokens_count--;
totp_full_save_config_file(plugin_state);
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
break;
}
case AppSettings: {
if(!scene_state->current_token_index.is_null) {
AppSettingsSceneContext app_settings_context = {
.current_token_index = scene_state->current_token_index.value};
totp_scene_director_activate_scene(
plugin_state, TotpSceneAppSettings, &app_settings_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneAppSettings, NULL);
}
break;
}
default:
break;
}
break;
case InputKeyBack: {
if(!scene_state->current_token_index.is_null) {
GenerateTokenSceneContext generate_scene_context = {
.current_token_index = scene_state->current_token_index.value};
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, &generate_scene_context);
} else {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
break;
}
default:
break;
}
return true;
}
@ -194,6 +200,6 @@ void totp_scene_token_menu_deactivate(PluginState* plugin_state) {
plugin_state->current_scene_state = NULL;
}
void totp_scene_token_menu_free(PluginState* plugin_state) {
void totp_scene_token_menu_free(const PluginState* plugin_state) {
UNUSED(plugin_state);
}

View File

@ -7,14 +7,14 @@
#include "../../types/plugin_event.h"
typedef struct {
uint8_t current_token_index;
uint16_t current_token_index;
} TokenMenuSceneContext;
void totp_scene_token_menu_init(PluginState* plugin_state);
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(PluginEvent* const event, 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(PluginState* plugin_state);
void totp_scene_token_menu_free(const PluginState* plugin_state);

View File

@ -9,7 +9,7 @@
#include "commands/timezone/timezone.h"
#include "commands/help/help.h"
static void totp_cli_print_unknown_command(FuriString* unknown_command) {
static void totp_cli_print_unknown_command(const FuriString* unknown_command) {
TOTP_CLI_PRINTF(
"Command \"%s\" is unknown. Use \"" TOTP_CLI_COMMAND_HELP
"\" command to get list of available commands.",

View File

@ -1,7 +1,7 @@
#include "cli_helpers.h"
#include <cli/cli.h>
bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli) {
bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) {
if(plugin_state->current_scene == TotpSceneAuthentication) {
TOTP_CLI_PRINTF("Pleases enter PIN on your flipper device\r\n");
@ -11,9 +11,8 @@ bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli) {
}
TOTP_CLI_DELETE_LAST_LINE();
fflush(stdout);
if(plugin_state->current_scene == TotpSceneAuthentication) {
if(plugin_state->current_scene == TotpSceneAuthentication) { //-V547
return false;
}
}

View File

@ -13,16 +13,28 @@
#define DOCOPT_OPTIONS "[options]"
#define DOCOPT_DEFAULT(val) "[default: " val "]"
#define TOTP_CLI_PRINTF(format, ...) \
_Pragma(STRINGIFY(GCC diagnostic push)); \
_Pragma(STRINGIFY(GCC diagnostic ignored "-Wdouble-promotion")); \
printf(format, ##__VA_ARGS__); \
_Pragma(STRINGIFY(GCC diagnostic pop));
#define TOTP_CLI_PRINTF(format, ...) \
do { \
_Pragma(STRINGIFY(GCC diagnostic push)) \
_Pragma(STRINGIFY(GCC diagnostic ignored "-Wdouble-promotion")) \
printf(format, ##__VA_ARGS__); \
_Pragma(STRINGIFY(GCC diagnostic pop)) \
} while(false)
#define TOTP_CLI_DELETE_LAST_LINE() \
TOTP_CLI_PRINTF("\033[A\33[2K\r"); \
fflush(stdout)
#define TOTP_CLI_DELETE_CURRENT_LINE() \
TOTP_CLI_PRINTF("\33[2K\r"); \
fflush(stdout)
#define TOTP_CLI_DELETE_LAST_CHAR() \
TOTP_CLI_PRINTF("\b \b"); \
fflush(stdout)
#define TOTP_CLI_DELETE_LAST_LINE() TOTP_CLI_PRINTF("\033[A\33[2K\r")
#define TOTP_CLI_DELETE_CURRENT_LINE() TOTP_CLI_PRINTF("\33[2K\r")
#define TOTP_CLI_PRINT_INVALID_ARGUMENTS() \
TOTP_CLI_PRINTF( \
"Invalid command arguments. use \"help\" command to get list of available commands")
bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli);
bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli);

View File

@ -14,7 +14,7 @@
#define TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "-d"
#define TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "-u"
static bool token_info_set_digits_from_str(TokenInfo* token_info, FuriString* str) {
static bool token_info_set_digits_from_str(TokenInfo* token_info, const FuriString* str) {
switch(furi_string_get_char(str, 0)) {
case '6':
token_info->digits = TOTP_6_DIGITS;
@ -22,12 +22,14 @@ static bool token_info_set_digits_from_str(TokenInfo* token_info, FuriString* st
case '8':
token_info->digits = TOTP_8_DIGITS;
return true;
default:
break;
}
return false;
}
static bool token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str) {
static bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) {
if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) {
token_info->algo = SHA1;
return true;
@ -79,10 +81,53 @@ void totp_cli_command_add_docopt_options() {
TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n");
}
static void furi_string_secure_free(FuriString* str) {
for(long i = furi_string_size(str) - 1; i >= 0; i--) {
furi_string_set_char(str, i, '\0');
}
furi_string_free(str);
}
static bool totp_cli_read_secret(Cli* cli, FuriString* out_str, bool mask_user_input) {
uint8_t c;
while(cli_read(cli, &c, 1) == 1) {
if(c == CliSymbolAsciiEsc) {
// Some keys generating escape-sequences
// We need to ignore them as we case about alpha-numerics only
uint8_t c2;
cli_read_timeout(cli, &c2, 1, 0);
cli_read_timeout(cli, &c2, 1, 0);
} else if(c == CliSymbolAsciiETX) {
TOTP_CLI_DELETE_CURRENT_LINE();
TOTP_CLI_PRINTF("Cancelled by user\r\n");
return false;
} else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
if(mask_user_input) {
putc('*', stdout);
} else {
putc(c, stdout);
}
fflush(stdout);
furi_string_push_back(out_str, c);
} else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
size_t out_str_size = furi_string_size(out_str);
if(out_str_size > 0) {
TOTP_CLI_DELETE_LAST_CHAR();
furi_string_left(out_str, out_str_size - 1);
}
} else if(c == CliSymbolAsciiCR) {
cli_nl();
break;
}
}
TOTP_CLI_DELETE_LAST_LINE();
return true;
}
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
FuriString* temp_str = furi_string_alloc();
const char* temp_cstr;
TokenInfo* token_info = token_info_alloc();
// Reading token name
@ -93,9 +138,10 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
return;
}
temp_cstr = furi_string_get_cstr(temp_str);
token_info->name = malloc(strlen(temp_cstr) + 1);
strcpy(token_info->name, temp_cstr);
size_t temp_cstr_len = furi_string_size(temp_str);
token_info->name = malloc(temp_cstr_len + 1);
furi_check(token_info->name != NULL);
strlcpy(token_info->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1);
// Read optional arguments
bool mask_user_input = true;
@ -142,59 +188,25 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
// Reading token secret
furi_string_reset(temp_str);
TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]\r\n");
uint8_t c;
while(cli_read(cli, &c, 1) == 1) {
if(c == CliSymbolAsciiEsc) {
uint8_t c2;
cli_read_timeout(cli, &c2, 1, 0);
cli_read_timeout(cli, &c2, 1, 0);
} else if(c == CliSymbolAsciiETX) {
TOTP_CLI_DELETE_CURRENT_LINE();
TOTP_CLI_PRINTF("Cancelled by user");
furi_string_free(temp_str);
token_info_free(token_info);
return;
} else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
if(mask_user_input) {
putc('*', stdout);
} else {
putc(c, stdout);
}
fflush(stdout);
furi_string_push_back(temp_str, c);
} else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
size_t temp_str_size = furi_string_size(temp_str);
if(temp_str_size > 0) {
TOTP_CLI_PRINTF("\b \b");
fflush(stdout);
furi_string_left(temp_str, temp_str_size - 1);
}
} else if(c == CliSymbolAsciiCR) {
cli_nl();
break;
}
}
temp_cstr = furi_string_get_cstr(temp_str);
TOTP_CLI_DELETE_LAST_LINE();
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
furi_string_free(temp_str);
if(!totp_cli_read_secret(cli, temp_str, mask_user_input) ||
!totp_cli_ensure_authenticated(plugin_state, cli)) {
furi_string_secure_free(temp_str);
token_info_free(token_info);
return;
}
if(!token_info_set_secret(token_info, temp_cstr, strlen(temp_cstr), plugin_state->iv)) {
if(!token_info_set_secret(
token_info,
furi_string_get_cstr(temp_str),
furi_string_size(temp_str),
plugin_state->iv)) {
TOTP_CLI_PRINTF("Token secret seems to be invalid and can not be parsed\r\n");
furi_string_free(temp_str);
furi_string_secure_free(temp_str);
token_info_free(token_info);
return;
}
furi_string_reset(temp_str);
furi_string_free(temp_str);
furi_string_secure_free(temp_str);
bool load_generate_token_scene = false;
if(plugin_state->current_scene == TotpSceneGenerateToken) {
@ -202,11 +214,7 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
load_generate_token_scene = true;
}
if(plugin_state->tokens_list == NULL) {
plugin_state->tokens_list = list_init_head(token_info);
} else {
list_add(plugin_state->tokens_list, token_info);
}
TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, token_info, furi_check);
plugin_state->tokens_count++;
totp_config_file_save_new_token(token_info);

View File

@ -13,6 +13,8 @@ static char* get_algo_as_cstr(TokenHashAlgo algo) {
return TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME;
case SHA512:
return TOTP_CONFIG_TOKEN_ALGO_SHA512_NAME;
default:
break;
}
return "UNKNOWN";
@ -24,6 +26,8 @@ static uint8_t get_digits_as_int(TokenDigitsCount digits) {
return 6;
case TOTP_8_DIGITS:
return 8;
default:
break;
}
return 6;

View File

@ -10,12 +10,14 @@
#define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf"
#define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup"
static uint8_t token_info_get_digits_as_int(TokenInfo* token_info) {
static uint8_t token_info_get_digits_as_int(const TokenInfo* token_info) {
switch(token_info->digits) {
case TOTP_6_DIGITS:
return 6;
case TOTP_8_DIGITS:
return 8;
default:
break;
}
return 6;
@ -29,10 +31,12 @@ static void token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits
case 8:
token_info->digits = TOTP_8_DIGITS;
break;
default:
break;
}
}
static char* token_info_get_algo_as_cstr(TokenInfo* token_info) {
static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) {
switch(token_info->algo) {
case SHA1:
return TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME;
@ -40,12 +44,14 @@ static char* token_info_get_algo_as_cstr(TokenInfo* token_info) {
return TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME;
case SHA512:
return TOTP_CONFIG_TOKEN_ALGO_SHA512_NAME;
default:
break;
}
return NULL;
}
static void token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str) {
static void token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) {
if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) {
token_info->algo = SHA1;
} else if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME) == 0) {
@ -152,7 +158,7 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
return fff_data_file;
}
void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_info) {
void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) {
flipper_format_seek_to_end(file);
flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name);
bool token_is_valid = token_info->token != NULL && token_info->token_length > 0;
@ -170,7 +176,7 @@ void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_inf
flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &digits_count_as_uint32, 1);
}
void totp_config_file_save_new_token(TokenInfo* token_info) {
void totp_config_file_save_new_token(const TokenInfo* token_info) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file = totp_open_config_file(cfg_storage);
@ -190,7 +196,7 @@ void totp_config_file_update_timezone_offset(float new_timezone_offset) {
totp_close_storage();
}
void totp_full_save_config_file(PluginState* const plugin_state) {
void totp_full_save_config_file(const PluginState* const plugin_state) {
Storage* storage = totp_open_storage();
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
@ -209,7 +215,7 @@ void totp_full_save_config_file(PluginState* const plugin_state) {
flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1);
ListNode* node = plugin_state->tokens_list;
while(node != NULL) {
TokenInfo* token_info = node->data;
const TokenInfo* token_info = node->data;
totp_config_file_save_new_token_i(fff_data_file, token_info);
node = node->next;
}
@ -283,6 +289,7 @@ void totp_config_file_load_base(PluginState* const plugin_state) {
if(flipper_format_get_value_count(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) &&
crypto_size > 0) {
plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size);
furi_check(plugin_state->crypto_verify_data != NULL);
plugin_state->crypto_verify_data_length = crypto_size;
if(!flipper_format_read_hex(
fff_data_file,
@ -333,7 +340,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
}
TokenLoadingResult result = TokenLoadingResultSuccess;
uint8_t index = 0;
uint16_t index = 0;
bool has_any_plain_secret = false;
while(true) {
@ -343,9 +350,10 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
TokenInfo* tokenInfo = token_info_alloc();
const char* temp_cstr = furi_string_get_cstr(temp_str);
tokenInfo->name = (char*)malloc(strlen(temp_cstr) + 1);
strcpy(tokenInfo->name, temp_cstr);
size_t temp_cstr_len = furi_string_size(temp_str);
tokenInfo->name = malloc(temp_cstr_len + 1);
furi_check(tokenInfo->name != NULL);
strlcpy(tokenInfo->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1);
uint32_t secret_bytes_count;
if(!flipper_format_get_value_count(
@ -355,9 +363,11 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
if(secret_bytes_count == 1) { // Plain secret key
if(flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) {
temp_cstr = furi_string_get_cstr(temp_str);
if(token_info_set_secret(
tokenInfo, temp_cstr, strlen(temp_cstr), &plugin_state->iv[0])) {
tokenInfo,
furi_string_get_cstr(temp_str),
furi_string_size(temp_str),
&plugin_state->iv[0])) {
FURI_LOG_W(LOGGING_TAG, "Token \"%s\" has plain secret", tokenInfo->name);
} else {
tokenInfo->token = NULL;
@ -376,6 +386,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
tokenInfo->token_length = secret_bytes_count;
if(secret_bytes_count > 0) {
tokenInfo->token = malloc(tokenInfo->token_length);
furi_check(tokenInfo->token != NULL);
if(!flipper_format_read_hex(
fff_data_file,
TOTP_CONFIG_KEY_TOKEN_SECRET,
@ -407,11 +418,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
FURI_LOG_D(LOGGING_TAG, "Found token \"%s\"", tokenInfo->name);
if(plugin_state->tokens_list == NULL) {
plugin_state->tokens_list = list_init_head(tokenInfo);
} else {
list_add(plugin_state->tokens_list, tokenInfo);
}
TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check);
index++;
}
@ -419,7 +426,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
plugin_state->tokens_count = index;
plugin_state->token_list_loaded = true;
FURI_LOG_D(LOGGING_TAG, "Found %" PRIu8 " tokens", index);
FURI_LOG_D(LOGGING_TAG, "Found %" PRIu16 " tokens", index);
furi_string_free(temp_str);
totp_close_config_file(fff_data_file);

View File

@ -16,8 +16,8 @@ Storage* totp_open_storage();
void totp_close_storage();
FlipperFormat* totp_open_config_file(Storage* storage);
void totp_close_config_file(FlipperFormat* file);
void totp_full_save_config_file(PluginState* const plugin_state);
void totp_full_save_config_file(const PluginState* const plugin_state);
void totp_config_file_load_base(PluginState* const plugin_state);
TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state);
void totp_config_file_save_new_token(TokenInfo* token_info);
void totp_config_file_save_new_token(const TokenInfo* token_info);
void totp_config_file_update_timezone_offset(float new_timezone_offset);

View File

@ -3,6 +3,7 @@
#include <furi_hal.h>
#include "../config/config.h"
#include "../../types/common.h"
#include "memset_s.h"
#define CRYPTO_KEY_SLOT 2
#define CRYPTO_VERIFY_KEY "FFF_Crypto_pass"
@ -11,28 +12,31 @@
uint8_t* totp_crypto_encrypt(
const uint8_t* plain_data,
const uint8_t plain_data_length,
const size_t plain_data_length,
const uint8_t* iv,
uint8_t* encrypted_data_length) {
size_t* encrypted_data_length) {
uint8_t* encrypted_data;
size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR;
if(remain) {
uint8_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR;
size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR;
uint8_t* plain_data_aligned = malloc(plain_data_aligned_length);
furi_check(plain_data_aligned != NULL);
memset(plain_data_aligned, 0, plain_data_aligned_length);
memcpy(plain_data_aligned, plain_data, plain_data_length);
encrypted_data = malloc(plain_data_aligned_length);
furi_check(encrypted_data != NULL);
*encrypted_data_length = plain_data_aligned_length;
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length);
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
memset(plain_data_aligned, 0, plain_data_aligned_length);
memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length);
free(plain_data_aligned);
} else {
encrypted_data = malloc(plain_data_length);
furi_check(encrypted_data != NULL);
*encrypted_data_length = plain_data_length;
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
@ -45,18 +49,19 @@ uint8_t* totp_crypto_encrypt(
uint8_t* totp_crypto_decrypt(
const uint8_t* encrypted_data,
const uint8_t encrypted_data_length,
const size_t encrypted_data_length,
const uint8_t* iv,
uint8_t* decrypted_data_length) {
size_t* decrypted_data_length) {
*decrypted_data_length = encrypted_data_length;
uint8_t* decrypted_data = malloc(*decrypted_data_length);
furi_check(decrypted_data != NULL);
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length);
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
return decrypted_data;
}
void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length) {
void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) {
if(plugin_state->crypto_verify_data == NULL) {
FURI_LOG_D(LOGGING_TAG, "Generating new IV");
furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE);
@ -92,6 +97,7 @@ void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_le
if(plugin_state->crypto_verify_data == NULL) {
FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data");
plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
furi_check(plugin_state->crypto_verify_data != NULL);
plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH;
Storage* storage = totp_open_storage();
FlipperFormat* config_file = totp_open_config_file(storage);
@ -118,8 +124,8 @@ void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_le
}
bool totp_crypto_verify_key(const PluginState* plugin_state) {
uint8_t decrypted_key_length;
uint8_t* decrypted_key = totp_crypto_decrypt(
size_t decrypted_key_length;
const uint8_t* decrypted_key = totp_crypto_decrypt(
plugin_state->crypto_verify_data,
plugin_state->crypto_verify_data_length,
&plugin_state->iv[0],

View File

@ -4,13 +4,13 @@
uint8_t* totp_crypto_encrypt(
const uint8_t* plain_data,
const uint8_t plain_data_length,
const size_t plain_data_length,
const uint8_t* iv,
uint8_t* encrypted_data_length);
size_t* encrypted_data_length);
uint8_t* totp_crypto_decrypt(
const uint8_t* encrypted_data,
const uint8_t encrypted_data_length,
const size_t encrypted_data_length,
const uint8_t* iv,
uint8_t* decrypted_data_length);
void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length);
size_t* decrypted_data_length);
void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length);
bool totp_crypto_verify_key(const PluginState* plugin_state);

View File

@ -0,0 +1,22 @@
#include "memset_s.h"
#define RSIZE_MAX 0x7fffffffffffffffUL
errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n) {
if(!s || smax > RSIZE_MAX) {
return EINVAL;
}
errno_t violation_present = 0;
if(n > smax) {
n = smax;
violation_present = EINVAL;
}
volatile unsigned char* v = s;
for(rsize_t i = 0u; i < n; ++i) {
*v++ = (unsigned char)c;
}
return violation_present;
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <errno.h>
#include <stdint.h>
#include <string.h>
#ifndef _RSIZE_T_DECLARED
typedef uint64_t rsize_t;
#define _RSIZE_T_DECLARED
#endif
#ifndef _ERRNOT_DECLARED
typedef int16_t errno_t; //-V677
#define _ERRNOT_DECLARED
#endif
errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n);

View File

@ -22,9 +22,6 @@
*/
/* Specification. */
#if HAVE_OPENSSL_SHA1
#define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
#endif
#include "sha1.h"
#include <stdint.h>
@ -37,8 +34,6 @@
#define SWAP(n) swap_uint32(n)
#endif
#if !HAVE_OPENSSL_SHA1
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (RFC 1321, 3.1: Step 1) */
static const unsigned char fillbuf[64] = {0x80, 0 /* , 0, 0, ... */};
@ -146,7 +141,7 @@ void sha1_process_bytes(const void* buffer, size_t len, struct sha1_ctx* ctx) {
#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(uint32_t) != 0)
if(UNALIGNED_P(buffer))
while(len > 64) {
sha1_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx);
sha1_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx); //-V1086
buffer = (const char*)buffer + 64;
len -= 64;
}
@ -232,86 +227,31 @@ void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx) {
words++;
}
R(a, b, c, d, e, F1, K1, x[0]);
R(e, a, b, c, d, F1, K1, x[1]);
R(d, e, a, b, c, F1, K1, x[2]);
R(c, d, e, a, b, F1, K1, x[3]);
R(b, c, d, e, a, F1, K1, x[4]);
R(a, b, c, d, e, F1, K1, x[5]);
R(e, a, b, c, d, F1, K1, x[6]);
R(d, e, a, b, c, F1, K1, x[7]);
R(c, d, e, a, b, F1, K1, x[8]);
R(b, c, d, e, a, F1, K1, x[9]);
R(a, b, c, d, e, F1, K1, x[10]);
R(e, a, b, c, d, F1, K1, x[11]);
R(d, e, a, b, c, F1, K1, x[12]);
R(c, d, e, a, b, F1, K1, x[13]);
R(b, c, d, e, a, F1, K1, x[14]);
R(a, b, c, d, e, F1, K1, x[15]);
R(e, a, b, c, d, F1, K1, M(16));
R(d, e, a, b, c, F1, K1, M(17));
R(c, d, e, a, b, F1, K1, M(18));
R(b, c, d, e, a, F1, K1, M(19));
R(a, b, c, d, e, F2, K2, M(20));
R(e, a, b, c, d, F2, K2, M(21));
R(d, e, a, b, c, F2, K2, M(22));
R(c, d, e, a, b, F2, K2, M(23));
R(b, c, d, e, a, F2, K2, M(24));
R(a, b, c, d, e, F2, K2, M(25));
R(e, a, b, c, d, F2, K2, M(26));
R(d, e, a, b, c, F2, K2, M(27));
R(c, d, e, a, b, F2, K2, M(28));
R(b, c, d, e, a, F2, K2, M(29));
R(a, b, c, d, e, F2, K2, M(30));
R(e, a, b, c, d, F2, K2, M(31));
R(d, e, a, b, c, F2, K2, M(32));
R(c, d, e, a, b, F2, K2, M(33));
R(b, c, d, e, a, F2, K2, M(34));
R(a, b, c, d, e, F2, K2, M(35));
R(e, a, b, c, d, F2, K2, M(36));
R(d, e, a, b, c, F2, K2, M(37));
R(c, d, e, a, b, F2, K2, M(38));
R(b, c, d, e, a, F2, K2, M(39));
R(a, b, c, d, e, F3, K3, M(40));
R(e, a, b, c, d, F3, K3, M(41));
R(d, e, a, b, c, F3, K3, M(42));
R(c, d, e, a, b, F3, K3, M(43));
R(b, c, d, e, a, F3, K3, M(44));
R(a, b, c, d, e, F3, K3, M(45));
R(e, a, b, c, d, F3, K3, M(46));
R(d, e, a, b, c, F3, K3, M(47));
R(c, d, e, a, b, F3, K3, M(48));
R(b, c, d, e, a, F3, K3, M(49));
R(a, b, c, d, e, F3, K3, M(50));
R(e, a, b, c, d, F3, K3, M(51));
R(d, e, a, b, c, F3, K3, M(52));
R(c, d, e, a, b, F3, K3, M(53));
R(b, c, d, e, a, F3, K3, M(54));
R(a, b, c, d, e, F3, K3, M(55));
R(e, a, b, c, d, F3, K3, M(56));
R(d, e, a, b, c, F3, K3, M(57));
R(c, d, e, a, b, F3, K3, M(58));
R(b, c, d, e, a, F3, K3, M(59));
R(a, b, c, d, e, F4, K4, M(60));
R(e, a, b, c, d, F4, K4, M(61));
R(d, e, a, b, c, F4, K4, M(62));
R(c, d, e, a, b, F4, K4, M(63));
R(b, c, d, e, a, F4, K4, M(64));
R(a, b, c, d, e, F4, K4, M(65));
R(e, a, b, c, d, F4, K4, M(66));
R(d, e, a, b, c, F4, K4, M(67));
R(c, d, e, a, b, F4, K4, M(68));
R(b, c, d, e, a, F4, K4, M(69));
R(a, b, c, d, e, F4, K4, M(70));
R(e, a, b, c, d, F4, K4, M(71));
R(d, e, a, b, c, F4, K4, M(72));
R(c, d, e, a, b, F4, K4, M(73));
R(b, c, d, e, a, F4, K4, M(74));
R(a, b, c, d, e, F4, K4, M(75));
R(e, a, b, c, d, F4, K4, M(76));
R(d, e, a, b, c, F4, K4, M(77));
R(c, d, e, a, b, F4, K4, M(78));
R(b, c, d, e, a, F4, K4, M(79));
for(int i = 0; i < 80; i++) {
uint32_t xx = i < 16 ? x[i] : M(i);
uint32_t ki = i / 20;
switch(ki) {
case 0:
R(a, b, c, d, e, F1, K1, xx);
break;
case 1:
R(a, b, c, d, e, F2, K2, xx);
break;
case 2:
R(a, b, c, d, e, F3, K3, xx);
break;
default:
R(a, b, c, d, e, F4, K4, xx);
break;
}
uint32_t tt = a;
a = e;
e = d;
d = c;
c = b;
b = tt;
}
a = ctx->A += a;
b = ctx->B += b;
@ -321,8 +261,6 @@ void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx) {
}
}
#endif
/*
* Hey Emacs!
* Local Variables:

View File

@ -21,23 +21,12 @@
#include <stdio.h>
#include <stdint.h>
#if HAVE_OPENSSL_SHA1
#ifndef OPENSSL_API_COMPAT
#define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
#endif
#include <openssl/sha.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define SHA1_DIGEST_SIZE 20
#if HAVE_OPENSSL_SHA1
#define GL_OPENSSL_NAME 1
#include "gl_openssl.h"
#else
/* Structure to save state of computation between the single steps. */
struct sha1_ctx {
uint32_t A;
@ -83,16 +72,6 @@ extern void* sha1_read_ctx(const struct sha1_ctx* ctx, void* restrict resbuf);
digest. */
extern void* sha1_buffer(const char* buffer, size_t len, void* restrict resblock);
#endif
/* Compute SHA1 message digest for bytes read from STREAM.
STREAM is an open file stream. Regular files are handled more efficiently.
The contents of STREAM from its current position to its end will be read.
The case that the last operation on STREAM was an 'ungetc' is not supported.
The resulting message digest number will be written into the 20 bytes
beginning at RESBLOCK. */
extern int sha1_stream(FILE* stream, void* resblock);
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,4 @@
/* sha256.c - Functions to compute SHA256 and SHA224 message digest of files or
/* sha256.c - Functions to compute SHA256 message digest of files or
memory blocks according to the NIST specification FIPS-180-2.
Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc.
@ -21,9 +21,6 @@
*/
/* Specification. */
#if HAVE_OPENSSL_SHA256
#define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
#endif
#include "sha256.h"
#include <stdint.h>
@ -36,8 +33,6 @@
#define SWAP(n) swap_uint32(n)
#endif
#if !HAVE_OPENSSL_SHA256
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. */
static const unsigned char fillbuf[64] = {0x80, 0 /* , 0, 0, ... */};
@ -61,20 +56,6 @@ void sha256_init_ctx(struct sha256_ctx* ctx) {
ctx->buflen = 0;
}
void sha224_init_ctx(struct sha256_ctx* ctx) {
ctx->state[0] = 0xc1059ed8UL;
ctx->state[1] = 0x367cd507UL;
ctx->state[2] = 0x3070dd17UL;
ctx->state[3] = 0xf70e5939UL;
ctx->state[4] = 0xffc00b31UL;
ctx->state[5] = 0x68581511UL;
ctx->state[6] = 0x64f98fa7UL;
ctx->state[7] = 0xbefa4fa4UL;
ctx->total[0] = ctx->total[1] = 0;
ctx->buflen = 0;
}
/* Copy the value from v into the memory location pointed to by *CP,
If your architecture allows unaligned access, this is equivalent to
* (__typeof__ (v) *) cp = v */
@ -93,15 +74,6 @@ void* sha256_read_ctx(const struct sha256_ctx* ctx, void* resbuf) {
return resbuf;
}
void* sha224_read_ctx(const struct sha256_ctx* ctx, void* resbuf) {
int i;
char* r = resbuf;
for(i = 0; i < 7; i++) set_uint32(r + i * sizeof ctx->state[0], SWAP(ctx->state[i]));
return resbuf;
}
/* Process the remaining bytes in the internal buffer and the usual
prolog according to the standard and write the result to RESBUF. */
static void sha256_conclude_ctx(struct sha256_ctx* ctx) {
@ -130,11 +102,6 @@ void* sha256_finish_ctx(struct sha256_ctx* ctx, void* resbuf) {
return sha256_read_ctx(ctx, resbuf);
}
void* sha224_finish_ctx(struct sha256_ctx* ctx, void* resbuf) {
sha256_conclude_ctx(ctx);
return sha224_read_ctx(ctx, resbuf);
}
/* Compute SHA256 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
@ -152,19 +119,6 @@ void* sha256_buffer(const char* buffer, size_t len, void* resblock) {
return sha256_finish_ctx(&ctx, resblock);
}
void* sha224_buffer(const char* buffer, size_t len, void* resblock) {
struct sha256_ctx ctx;
/* Initialize the computation context. */
sha224_init_ctx(&ctx);
/* Process whole buffer but last len % 64 bytes. */
sha256_process_bytes(buffer, len, &ctx);
/* Put result in desired memory area. */
return sha224_finish_ctx(&ctx, resblock);
}
void sha256_process_bytes(const void* buffer, size_t len, struct sha256_ctx* ctx) {
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
@ -194,7 +148,7 @@ void sha256_process_bytes(const void* buffer, size_t len, struct sha256_ctx* ctx
#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(uint32_t) != 0)
if(UNALIGNED_P(buffer))
while(len > 64) {
sha256_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx);
sha256_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx); //-V1086
buffer = (const char*)buffer + 64;
len -= 64;
}
@ -299,70 +253,19 @@ void sha256_process_block(const void* buffer, size_t len, struct sha256_ctx* ctx
words++;
}
R(a, b, c, d, e, f, g, h, K(0), x[0]);
R(h, a, b, c, d, e, f, g, K(1), x[1]);
R(g, h, a, b, c, d, e, f, K(2), x[2]);
R(f, g, h, a, b, c, d, e, K(3), x[3]);
R(e, f, g, h, a, b, c, d, K(4), x[4]);
R(d, e, f, g, h, a, b, c, K(5), x[5]);
R(c, d, e, f, g, h, a, b, K(6), x[6]);
R(b, c, d, e, f, g, h, a, K(7), x[7]);
R(a, b, c, d, e, f, g, h, K(8), x[8]);
R(h, a, b, c, d, e, f, g, K(9), x[9]);
R(g, h, a, b, c, d, e, f, K(10), x[10]);
R(f, g, h, a, b, c, d, e, K(11), x[11]);
R(e, f, g, h, a, b, c, d, K(12), x[12]);
R(d, e, f, g, h, a, b, c, K(13), x[13]);
R(c, d, e, f, g, h, a, b, K(14), x[14]);
R(b, c, d, e, f, g, h, a, K(15), x[15]);
R(a, b, c, d, e, f, g, h, K(16), M(16));
R(h, a, b, c, d, e, f, g, K(17), M(17));
R(g, h, a, b, c, d, e, f, K(18), M(18));
R(f, g, h, a, b, c, d, e, K(19), M(19));
R(e, f, g, h, a, b, c, d, K(20), M(20));
R(d, e, f, g, h, a, b, c, K(21), M(21));
R(c, d, e, f, g, h, a, b, K(22), M(22));
R(b, c, d, e, f, g, h, a, K(23), M(23));
R(a, b, c, d, e, f, g, h, K(24), M(24));
R(h, a, b, c, d, e, f, g, K(25), M(25));
R(g, h, a, b, c, d, e, f, K(26), M(26));
R(f, g, h, a, b, c, d, e, K(27), M(27));
R(e, f, g, h, a, b, c, d, K(28), M(28));
R(d, e, f, g, h, a, b, c, K(29), M(29));
R(c, d, e, f, g, h, a, b, K(30), M(30));
R(b, c, d, e, f, g, h, a, K(31), M(31));
R(a, b, c, d, e, f, g, h, K(32), M(32));
R(h, a, b, c, d, e, f, g, K(33), M(33));
R(g, h, a, b, c, d, e, f, K(34), M(34));
R(f, g, h, a, b, c, d, e, K(35), M(35));
R(e, f, g, h, a, b, c, d, K(36), M(36));
R(d, e, f, g, h, a, b, c, K(37), M(37));
R(c, d, e, f, g, h, a, b, K(38), M(38));
R(b, c, d, e, f, g, h, a, K(39), M(39));
R(a, b, c, d, e, f, g, h, K(40), M(40));
R(h, a, b, c, d, e, f, g, K(41), M(41));
R(g, h, a, b, c, d, e, f, K(42), M(42));
R(f, g, h, a, b, c, d, e, K(43), M(43));
R(e, f, g, h, a, b, c, d, K(44), M(44));
R(d, e, f, g, h, a, b, c, K(45), M(45));
R(c, d, e, f, g, h, a, b, K(46), M(46));
R(b, c, d, e, f, g, h, a, K(47), M(47));
R(a, b, c, d, e, f, g, h, K(48), M(48));
R(h, a, b, c, d, e, f, g, K(49), M(49));
R(g, h, a, b, c, d, e, f, K(50), M(50));
R(f, g, h, a, b, c, d, e, K(51), M(51));
R(e, f, g, h, a, b, c, d, K(52), M(52));
R(d, e, f, g, h, a, b, c, K(53), M(53));
R(c, d, e, f, g, h, a, b, K(54), M(54));
R(b, c, d, e, f, g, h, a, K(55), M(55));
R(a, b, c, d, e, f, g, h, K(56), M(56));
R(h, a, b, c, d, e, f, g, K(57), M(57));
R(g, h, a, b, c, d, e, f, K(58), M(58));
R(f, g, h, a, b, c, d, e, K(59), M(59));
R(e, f, g, h, a, b, c, d, K(60), M(60));
R(d, e, f, g, h, a, b, c, K(61), M(61));
R(c, d, e, f, g, h, a, b, K(62), M(62));
R(b, c, d, e, f, g, h, a, K(63), M(63));
for(int i = 0; i < 64; i++) {
uint32_t xx = i < 16 ? x[i] : M(i);
R(a, b, c, d, e, f, g, h, K(i), xx);
uint32_t tt = a;
a = h;
h = g;
g = f;
f = e;
e = d;
d = c;
c = b;
b = tt;
}
a = ctx->state[0] += a;
b = ctx->state[1] += b;
@ -375,8 +278,6 @@ void sha256_process_block(const void* buffer, size_t len, struct sha256_ctx* ctx
}
}
#endif
/*
* Hey Emacs!
* Local Variables:

View File

@ -1,4 +1,4 @@
/* Declarations of functions and data types used for SHA256 and SHA224 sum
/* Declarations of functions and data types used for SHA256 sum
library functions.
Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc.
@ -20,26 +20,12 @@
#include <stdio.h>
#include <stdint.h>
#if HAVE_OPENSSL_SHA256
#ifndef OPENSSL_API_COMPAT
#define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
#endif
#include <openssl/sha.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
enum { SHA224_DIGEST_SIZE = 224 / 8 };
enum { SHA256_DIGEST_SIZE = 256 / 8 };
#if HAVE_OPENSSL_SHA256
#define GL_OPENSSL_NAME 224
#include "gl_openssl.h"
#define GL_OPENSSL_NAME 256
#include "gl_openssl.h"
#else
/* Structure to save state of computation between the single steps. */
struct sha256_ctx {
uint32_t state[8];
@ -51,7 +37,6 @@ struct sha256_ctx {
/* Initialize structure containing state of computation. */
extern void sha256_init_ctx(struct sha256_ctx* ctx);
extern void sha224_init_ctx(struct sha256_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
@ -70,31 +55,17 @@ extern void sha256_process_bytes(const void* buffer, size_t len, struct sha256_c
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
extern void* sha256_finish_ctx(struct sha256_ctx* ctx, void* restrict resbuf);
extern void* sha224_finish_ctx(struct sha256_ctx* ctx, void* restrict resbuf);
/* Put result from CTX in first 32 (28) bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest. */
extern void* sha256_read_ctx(const struct sha256_ctx* ctx, void* restrict resbuf);
extern void* sha224_read_ctx(const struct sha256_ctx* ctx, void* restrict resbuf);
/* Compute SHA256 (SHA224) message digest for LEN bytes beginning at BUFFER.
/* Compute SHA256 message digest for LEN bytes beginning at BUFFER.
The result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
extern void* sha256_buffer(const char* buffer, size_t len, void* restrict resblock);
extern void* sha224_buffer(const char* buffer, size_t len, void* restrict resblock);
#endif
/* Compute SHA256 (SHA224) message digest for bytes read from STREAM.
STREAM is an open file stream. Regular files are handled more efficiently.
The contents of STREAM from its current position to its end will be read.
The case that the last operation on STREAM was an 'ungetc' is not supported.
The resulting message digest number will be written into the 32 (28) bytes
beginning at RESBLOCK. */
extern int sha256_stream(FILE* stream, void* resblock);
extern int sha224_stream(FILE* stream, void* resblock);
#ifdef __cplusplus
}

View File

@ -1,4 +1,4 @@
/* sha512.c - Functions to compute SHA512 and SHA384 message digest of files or
/* sha512.c - Functions to compute SHA512 message digest of files or
memory blocks according to the NIST specification FIPS-180-2.
Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc.
@ -21,9 +21,6 @@
*/
/* Specification. */
#if HAVE_OPENSSL_SHA512
#define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
#endif
#include "sha512.h"
#include <stdint.h>
@ -36,8 +33,6 @@
#define SWAP(n) swap_uint64(n)
#endif
#if !HAVE_OPENSSL_SHA512
/* This array contains the bytes used to pad the buffer to the next
128-byte boundary. */
static const unsigned char fillbuf[128] = {0x80, 0 /* , 0, 0, ... */};
@ -61,20 +56,6 @@ void sha512_init_ctx(struct sha512_ctx* ctx) {
ctx->buflen = 0;
}
void sha384_init_ctx(struct sha512_ctx* ctx) {
ctx->state[0] = u64hilo(0xcbbb9d5d, 0xc1059ed8);
ctx->state[1] = u64hilo(0x629a292a, 0x367cd507);
ctx->state[2] = u64hilo(0x9159015a, 0x3070dd17);
ctx->state[3] = u64hilo(0x152fecd8, 0xf70e5939);
ctx->state[4] = u64hilo(0x67332667, 0xffc00b31);
ctx->state[5] = u64hilo(0x8eb44a87, 0x68581511);
ctx->state[6] = u64hilo(0xdb0c2e0d, 0x64f98fa7);
ctx->state[7] = u64hilo(0x47b5481d, 0xbefa4fa4);
ctx->total[0] = ctx->total[1] = u64lo(0);
ctx->buflen = 0;
}
/* Copy the value from V into the memory location pointed to by *CP,
If your architecture allows unaligned access, this is equivalent to
* (__typeof__ (v) *) cp = v */
@ -93,15 +74,6 @@ void* sha512_read_ctx(const struct sha512_ctx* ctx, void* resbuf) {
return resbuf;
}
void* sha384_read_ctx(const struct sha512_ctx* ctx, void* resbuf) {
int i;
char* r = resbuf;
for(i = 0; i < 6; i++) set_uint64(r + i * sizeof ctx->state[0], SWAP(ctx->state[i]));
return resbuf;
}
/* Process the remaining bytes in the internal buffer and the usual
prolog according to the standard and write the result to RESBUF. */
static void sha512_conclude_ctx(struct sha512_ctx* ctx) {
@ -132,11 +104,6 @@ void* sha512_finish_ctx(struct sha512_ctx* ctx, void* resbuf) {
return sha512_read_ctx(ctx, resbuf);
}
void* sha384_finish_ctx(struct sha512_ctx* ctx, void* resbuf) {
sha512_conclude_ctx(ctx);
return sha384_read_ctx(ctx, resbuf);
}
/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
@ -154,19 +121,6 @@ void* sha512_buffer(const char* buffer, size_t len, void* resblock) {
return sha512_finish_ctx(&ctx, resblock);
}
void* sha384_buffer(const char* buffer, size_t len, void* resblock) {
struct sha512_ctx ctx;
/* Initialize the computation context. */
sha384_init_ctx(&ctx);
/* Process whole buffer but last len % 128 bytes. */
sha512_process_bytes(buffer, len, &ctx);
/* Put result in desired memory area. */
return sha384_finish_ctx(&ctx, resblock);
}
void sha512_process_bytes(const void* buffer, size_t len, struct sha512_ctx* ctx) {
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
@ -196,7 +150,7 @@ void sha512_process_bytes(const void* buffer, size_t len, struct sha512_ctx* ctx
#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(u64) != 0)
if(UNALIGNED_P(buffer))
while(len > 128) {
sha512_process_block(memcpy(ctx->buffer, buffer, 128), 128, ctx);
sha512_process_block(memcpy(ctx->buffer, buffer, 128), 128, ctx); //-V1086
buffer = (const char*)buffer + 128;
len -= 128;
}
@ -328,86 +282,19 @@ void sha512_process_block(const void* buffer, size_t len, struct sha512_ctx* ctx
words++;
}
R(a, b, c, d, e, f, g, h, K(0), x[0]);
R(h, a, b, c, d, e, f, g, K(1), x[1]);
R(g, h, a, b, c, d, e, f, K(2), x[2]);
R(f, g, h, a, b, c, d, e, K(3), x[3]);
R(e, f, g, h, a, b, c, d, K(4), x[4]);
R(d, e, f, g, h, a, b, c, K(5), x[5]);
R(c, d, e, f, g, h, a, b, K(6), x[6]);
R(b, c, d, e, f, g, h, a, K(7), x[7]);
R(a, b, c, d, e, f, g, h, K(8), x[8]);
R(h, a, b, c, d, e, f, g, K(9), x[9]);
R(g, h, a, b, c, d, e, f, K(10), x[10]);
R(f, g, h, a, b, c, d, e, K(11), x[11]);
R(e, f, g, h, a, b, c, d, K(12), x[12]);
R(d, e, f, g, h, a, b, c, K(13), x[13]);
R(c, d, e, f, g, h, a, b, K(14), x[14]);
R(b, c, d, e, f, g, h, a, K(15), x[15]);
R(a, b, c, d, e, f, g, h, K(16), M(16));
R(h, a, b, c, d, e, f, g, K(17), M(17));
R(g, h, a, b, c, d, e, f, K(18), M(18));
R(f, g, h, a, b, c, d, e, K(19), M(19));
R(e, f, g, h, a, b, c, d, K(20), M(20));
R(d, e, f, g, h, a, b, c, K(21), M(21));
R(c, d, e, f, g, h, a, b, K(22), M(22));
R(b, c, d, e, f, g, h, a, K(23), M(23));
R(a, b, c, d, e, f, g, h, K(24), M(24));
R(h, a, b, c, d, e, f, g, K(25), M(25));
R(g, h, a, b, c, d, e, f, K(26), M(26));
R(f, g, h, a, b, c, d, e, K(27), M(27));
R(e, f, g, h, a, b, c, d, K(28), M(28));
R(d, e, f, g, h, a, b, c, K(29), M(29));
R(c, d, e, f, g, h, a, b, K(30), M(30));
R(b, c, d, e, f, g, h, a, K(31), M(31));
R(a, b, c, d, e, f, g, h, K(32), M(32));
R(h, a, b, c, d, e, f, g, K(33), M(33));
R(g, h, a, b, c, d, e, f, K(34), M(34));
R(f, g, h, a, b, c, d, e, K(35), M(35));
R(e, f, g, h, a, b, c, d, K(36), M(36));
R(d, e, f, g, h, a, b, c, K(37), M(37));
R(c, d, e, f, g, h, a, b, K(38), M(38));
R(b, c, d, e, f, g, h, a, K(39), M(39));
R(a, b, c, d, e, f, g, h, K(40), M(40));
R(h, a, b, c, d, e, f, g, K(41), M(41));
R(g, h, a, b, c, d, e, f, K(42), M(42));
R(f, g, h, a, b, c, d, e, K(43), M(43));
R(e, f, g, h, a, b, c, d, K(44), M(44));
R(d, e, f, g, h, a, b, c, K(45), M(45));
R(c, d, e, f, g, h, a, b, K(46), M(46));
R(b, c, d, e, f, g, h, a, K(47), M(47));
R(a, b, c, d, e, f, g, h, K(48), M(48));
R(h, a, b, c, d, e, f, g, K(49), M(49));
R(g, h, a, b, c, d, e, f, K(50), M(50));
R(f, g, h, a, b, c, d, e, K(51), M(51));
R(e, f, g, h, a, b, c, d, K(52), M(52));
R(d, e, f, g, h, a, b, c, K(53), M(53));
R(c, d, e, f, g, h, a, b, K(54), M(54));
R(b, c, d, e, f, g, h, a, K(55), M(55));
R(a, b, c, d, e, f, g, h, K(56), M(56));
R(h, a, b, c, d, e, f, g, K(57), M(57));
R(g, h, a, b, c, d, e, f, K(58), M(58));
R(f, g, h, a, b, c, d, e, K(59), M(59));
R(e, f, g, h, a, b, c, d, K(60), M(60));
R(d, e, f, g, h, a, b, c, K(61), M(61));
R(c, d, e, f, g, h, a, b, K(62), M(62));
R(b, c, d, e, f, g, h, a, K(63), M(63));
R(a, b, c, d, e, f, g, h, K(64), M(64));
R(h, a, b, c, d, e, f, g, K(65), M(65));
R(g, h, a, b, c, d, e, f, K(66), M(66));
R(f, g, h, a, b, c, d, e, K(67), M(67));
R(e, f, g, h, a, b, c, d, K(68), M(68));
R(d, e, f, g, h, a, b, c, K(69), M(69));
R(c, d, e, f, g, h, a, b, K(70), M(70));
R(b, c, d, e, f, g, h, a, K(71), M(71));
R(a, b, c, d, e, f, g, h, K(72), M(72));
R(h, a, b, c, d, e, f, g, K(73), M(73));
R(g, h, a, b, c, d, e, f, K(74), M(74));
R(f, g, h, a, b, c, d, e, K(75), M(75));
R(e, f, g, h, a, b, c, d, K(76), M(76));
R(d, e, f, g, h, a, b, c, K(77), M(77));
R(c, d, e, f, g, h, a, b, K(78), M(78));
R(b, c, d, e, f, g, h, a, K(79), M(79));
for(int i = 0; i < 80; i++) {
u64 xx = i < 16 ? x[i] : M(i);
R(a, b, c, d, e, f, g, h, K(i), xx);
u64 tt = a;
a = h;
h = g;
g = f;
f = e;
e = d;
d = c;
c = b;
b = tt;
}
a = ctx->state[0] = u64plus(ctx->state[0], a);
b = ctx->state[1] = u64plus(ctx->state[1], b);
@ -420,8 +307,6 @@ void sha512_process_block(const void* buffer, size_t len, struct sha512_ctx* ctx
}
}
#endif
/*
* Hey Emacs!
* Local Variables:

View File

@ -20,26 +20,12 @@
#include <stdio.h>
#include "u64.h"
#if HAVE_OPENSSL_SHA512
#ifndef OPENSSL_API_COMPAT
#define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
#endif
#include <openssl/sha.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
enum { SHA384_DIGEST_SIZE = 384 / 8 };
enum { SHA512_DIGEST_SIZE = 512 / 8 };
#if HAVE_OPENSSL_SHA512
#define GL_OPENSSL_NAME 384
#include "gl_openssl.h"
#define GL_OPENSSL_NAME 512
#include "gl_openssl.h"
#else
/* Structure to save state of computation between the single steps. */
struct sha512_ctx {
u64 state[8];
@ -51,7 +37,6 @@ struct sha512_ctx {
/* Initialize structure containing state of computation. */
extern void sha512_init_ctx(struct sha512_ctx* ctx);
extern void sha384_init_ctx(struct sha512_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
@ -70,7 +55,6 @@ extern void sha512_process_bytes(const void* buffer, size_t len, struct sha512_c
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
extern void* sha512_finish_ctx(struct sha512_ctx* ctx, void* restrict resbuf);
extern void* sha384_finish_ctx(struct sha512_ctx* ctx, void* restrict resbuf);
/* Put result from CTX in first 64 (48) bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
@ -79,25 +63,12 @@ extern void* sha384_finish_ctx(struct sha512_ctx* ctx, void* restrict resbuf);
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
extern void* sha512_read_ctx(const struct sha512_ctx* ctx, void* restrict resbuf);
extern void* sha384_read_ctx(const struct sha512_ctx* ctx, void* restrict resbuf);
/* Compute SHA512 (SHA384) message digest for LEN bytes beginning at BUFFER.
/* Compute SHA512 message digest for LEN bytes beginning at BUFFER.
The result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
extern void* sha512_buffer(const char* buffer, size_t len, void* restrict resblock);
extern void* sha384_buffer(const char* buffer, size_t len, void* restrict resblock);
#endif
/* Compute SHA512 (SHA384) message digest for bytes read from STREAM.
STREAM is an open file stream. Regular files are handled more efficiently.
The contents of STREAM from its current position to its end will be read.
The case that the last operation on STREAM was an 'ungetc' is not supported.
The resulting message digest number will be written into the 64 (48) bytes
beginning at RESBLOCK. */
extern int sha512_stream(FILE* stream, void* resblock);
extern int sha384_stream(FILE* stream, void* resblock);
#ifdef __cplusplus
}

View File

@ -1,20 +0,0 @@
/* uint64_t-like operations that work even on hosts lacking uint64_t
Copyright (C) 2012-2022 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#define _GL_U64_INLINE _GL_EXTERN_INLINE
#include "u64.h"
typedef int dummy;

View File

@ -26,7 +26,7 @@
#endif
/* Return X rotated left by N bits, where 0 < N < 64. */
#define u64rol(x, n) u64or(u64shl(x, n), u64shr(x, 64 - n))
#define u64rol(x, n) u64or(u64shl(x, n), u64shr(x, 64 - (n)))
/* Native implementations are trivial. See below for comments on what
these operations do. */

View File

@ -1,14 +1,16 @@
#include "list.h"
ListNode* list_init_head(void* data) {
ListNode* new = (ListNode*)malloc(sizeof(ListNode));
ListNode* new = malloc(sizeof(ListNode));
if(new == NULL) return NULL;
new->data = data;
new->next = NULL;
return new;
}
ListNode* list_add(ListNode* head, void* data) {
ListNode* new = (ListNode*)malloc(sizeof(ListNode));
ListNode* new = malloc(sizeof(ListNode));
if(new == NULL) return NULL;
new->data = data;
new->next = NULL;
@ -26,7 +28,7 @@ ListNode* list_add(ListNode* head, void* data) {
return head;
}
ListNode* list_find(ListNode* head, void* data) {
ListNode* list_find(ListNode* head, const void* data) {
ListNode* it;
for(it = head; it != NULL; it = it->next)
@ -66,7 +68,8 @@ ListNode* list_remove(ListNode* head, ListNode* ep) {
}
void list_free(ListNode* head) {
ListNode *it = head, *tmp;
ListNode* it = head;
ListNode* tmp;
while(it != NULL) {
tmp = it;

View File

@ -14,7 +14,7 @@ ListNode* list_add(
void* data); /* adds element with specified data to the end of the list and returns new head node. */
ListNode* list_find(
ListNode* head,
void* data); /* returns pointer of element with specified data in list. */
const void* data); /* returns pointer of element with specified data in list. */
ListNode* list_element_at(
ListNode* head,
uint16_t index); /* returns pointer of element with specified index in list. */
@ -22,3 +22,13 @@ ListNode* list_remove(
ListNode* head,
ListNode* ep); /* removes element from the list and returns new head node. */
void list_free(ListNode* head); /* deletes all elements of the list. */
#define TOTP_LIST_INIT_OR_ADD(head, item, assert) \
do { \
if(head == NULL) { \
head = list_init_head(item); \
assert(head != NULL); \
} else { \
assert(list_add(head, item) != NULL); \
} \
} while(false)

View File

@ -0,0 +1,17 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#define TOTP_NULLABLE_STRUCT(value_type) \
typedef struct TotpNullable_##value_type { \
bool is_null; \
value_type value; \
} TotpNullable_##value_type
#define TOTP_NULLABLE_NULL(s) s.is_null = true
#define TOTP_NULLABLE_VALUE(s, v) \
s.is_null = false; \
s.value = v
TOTP_NULLABLE_STRUCT(uint16_t);

View File

@ -0,0 +1,28 @@
#include "roll_value.h"
#define TOTP_ROLL_VALUE_FN(type, step_type) \
TOTP_ROLL_VALUE_FN_HEADER(type, step_type) { \
type v = *value; \
if(step > 0 && v > max - step) { \
if(overflow_behavior == RollOverflowBehaviorRoll) { \
v = min; \
} else if(overflow_behavior == RollOverflowBehaviorStop) { \
v = max; \
} \
} else if(step < 0 && v < min - step) { \
if(overflow_behavior == RollOverflowBehaviorRoll) { \
v = max; \
} else if(overflow_behavior == RollOverflowBehaviorStop) { \
v = min; \
} \
} else { \
v += step; \
} \
*value = v; \
}
TOTP_ROLL_VALUE_FN(int8_t, int8_t)
TOTP_ROLL_VALUE_FN(uint8_t, int8_t)
TOTP_ROLL_VALUE_FN(uint16_t, int16_t);

View File

@ -0,0 +1,17 @@
#pragma once
#include <stdint.h>
typedef enum { RollOverflowBehaviorStop, RollOverflowBehaviorRoll } TotpRollValueOverflowBehavior;
#define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \
void totp_roll_value_##type( \
type* value, \
step_type step, \
type min, \
type max, \
TotpRollValueOverflowBehavior overflow_behavior)
TOTP_ROLL_VALUE_FN_HEADER(int8_t, int8_t);
TOTP_ROLL_VALUE_FN_HEADER(uint8_t, int8_t);
TOTP_ROLL_VALUE_FN_HEADER(uint16_t, int16_t);

View File

@ -42,14 +42,15 @@ uint32_t otp_generate(
TOTP_ALGO algo,
uint8_t digits,
const uint8_t* plain_secret,
uint8_t plain_secret_length,
size_t plain_secret_length,
uint64_t input) {
uint8_t* hmac = malloc(64);
if(hmac == NULL) return OTP_ERROR;
memset(hmac, 0, 64);
uint64_t input_swapped = swap_uint64(input);
int hmac_len = (*(algo))(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, hmac);
int hmac_len = (*algo)(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, hmac);
if(hmac_len == 0) {
free(hmac);
return OTP_ERROR;
@ -80,7 +81,7 @@ uint32_t totp_at(
TOTP_ALGO algo,
uint8_t digits,
const uint8_t* plain_secret,
uint8_t plain_secret_length,
size_t plain_secret_length,
uint64_t for_time,
float timezone,
uint8_t interval) {
@ -96,9 +97,9 @@ uint32_t totp_at(
static int totp_algo_sha1(
const uint8_t* key,
uint8_t key_length,
size_t key_length,
const uint8_t* input,
uint8_t input_length,
size_t input_length,
uint8_t* output) {
hmac_sha1(key, key_length, input, input_length, output);
return HMAC_SHA1_RESULT_SIZE;
@ -106,9 +107,9 @@ static int totp_algo_sha1(
static int totp_algo_sha256(
const uint8_t* key,
uint8_t key_length,
size_t key_length,
const uint8_t* input,
uint8_t input_length,
size_t input_length,
uint8_t* output) {
hmac_sha256(key, key_length, input, input_length, output);
return HMAC_SHA256_RESULT_SIZE;
@ -116,9 +117,9 @@ static int totp_algo_sha256(
static int totp_algo_sha512(
const uint8_t* key,
uint8_t key_length,
size_t key_length,
const uint8_t* input,
uint8_t input_length,
size_t input_length,
uint8_t* output) {
hmac_sha512(key, key_length, input, input_length, output);
return HMAC_SHA512_RESULT_SIZE;

View File

@ -17,9 +17,9 @@
*/
typedef int (*TOTP_ALGO)(
const uint8_t* key,
uint8_t key_length,
size_t key_length,
const uint8_t* input,
uint8_t input_length,
size_t input_length,
uint8_t* output);
/*
@ -47,7 +47,7 @@ uint32_t totp_at(
TOTP_ALGO algo,
uint8_t digits,
const uint8_t* plain_secret,
uint8_t plain_secret_length,
size_t plain_secret_length,
uint64_t for_time,
float timezone,
uint8_t interval);

View File

@ -1,13 +0,0 @@
#pragma once
#include <totp_icons.h>
#include <inttypes.h>
#define ICON_ARROW_LEFT_8x9_WIDTH 8
#define ICON_ARROW_LEFT_8x9_HEIGHT 9
static const uint8_t ICON_ARROW_LEFT_8x9[] = {0x80, 0xe0, 0xf8, 0xfe, 0xff, 0xfe, 0xf8, 0xe0, 0x80};
#define ICON_ARROW_RIGHT_8x9_WIDTH 8
#define ICON_ARROW_RIGHT_8x9_HEIGHT 9
static const uint8_t ICON_ARROW_RIGHT_8x9[] =
{0x01, 0x07, 0x1f, 0x7f, 0xff, 0x7f, 0x1f, 0x07, 0x01};

View File

@ -1,11 +1,15 @@
#include "ui_controls.h"
#include <totp_icons.h>
#include "constants.h"
#include "icons.h"
#define TEXT_BOX_HEIGHT 13
#define TEXT_BOX_MARGIN 4
void ui_control_text_box_render(Canvas* const canvas, int8_t y, char* text, bool is_selected) {
void ui_control_text_box_render(
Canvas* const canvas,
int16_t y,
const char* text,
bool is_selected) {
if(y < -TEXT_BOX_HEIGHT) {
return;
}
@ -44,7 +48,7 @@ void ui_control_select_render(
int16_t x,
int16_t y,
uint8_t width,
char* text,
const char* text,
bool is_selected) {
if(y < -TEXT_BOX_HEIGHT) {
return;
@ -77,20 +81,10 @@ void ui_control_select_render(
canvas_draw_str_aligned(
canvas, x + (width >> 1), TEXT_BOX_MARGIN + 3 + y, AlignCenter, AlignTop, text);
canvas_draw_xbm(
canvas,
x + TEXT_BOX_MARGIN + 2,
TEXT_BOX_MARGIN + 2 + y,
ICON_ARROW_LEFT_8x9_WIDTH,
ICON_ARROW_LEFT_8x9_HEIGHT,
&ICON_ARROW_LEFT_8x9[0]);
canvas_draw_xbm(
canvas,
x + width - TEXT_BOX_MARGIN - 10,
TEXT_BOX_MARGIN + 2 + y,
ICON_ARROW_RIGHT_8x9_WIDTH,
ICON_ARROW_RIGHT_8x9_HEIGHT,
&ICON_ARROW_RIGHT_8x9[0]);
canvas_draw_icon(
canvas, x + TEXT_BOX_MARGIN + 2, TEXT_BOX_MARGIN + 2 + y, &I_totp_arrow_left_8x9);
canvas_draw_icon(
canvas, x + width - TEXT_BOX_MARGIN - 10, TEXT_BOX_MARGIN + 2 + y, &I_totp_arrow_right_8x9);
}
void ui_control_button_render(
@ -99,7 +93,7 @@ void ui_control_button_render(
int16_t y,
uint8_t width,
uint8_t height,
char* text,
const char* text,
bool is_selected) {
if(y < -height) {
return;

View File

@ -3,19 +3,23 @@
#include <inttypes.h>
#include <gui/gui.h>
void ui_control_text_box_render(Canvas* const canvas, int8_t y, char* text, bool is_selected);
void ui_control_text_box_render(
Canvas* const canvas,
int16_t y,
const char* text,
bool is_selected);
void ui_control_button_render(
Canvas* const canvas,
int16_t x,
int16_t y,
uint8_t width,
uint8_t height,
char* text,
const char* text,
bool is_selected);
void ui_control_select_render(
Canvas* const canvas,
int16_t x,
int16_t y,
uint8_t width,
char* text,
const char* text,
bool is_selected);

View File

@ -125,6 +125,7 @@ static void totp_plugin_state_free(PluginState* plugin_state) {
int32_t totp_app() {
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
PluginState* plugin_state = malloc(sizeof(PluginState));
furi_check(plugin_state != NULL);
if(!totp_plugin_state_init(plugin_state)) {
FURI_LOG_E(LOGGING_TAG, "App state initialization failed\r\n");
@ -154,22 +155,22 @@ int32_t totp_app() {
if(plugin_state->changing_scene) continue;
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = acquire_mutex_block(&state_mutex);
PluginState* plugin_state_m = acquire_mutex_block(&state_mutex);
if(event_status == FuriStatusOk) {
if(event.type == EventTypeKey) {
last_user_interaction_time = furi_get_tick();
}
processing = totp_scene_director_handle_event(&event, plugin_state);
processing = totp_scene_director_handle_event(&event, plugin_state_m);
} else if(
plugin_state->pin_set && plugin_state->current_scene != TotpSceneAuthentication &&
plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication &&
furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) {
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
totp_scene_director_activate_scene(plugin_state_m, TotpSceneAuthentication, NULL);
}
view_port_update(view_port);
release_mutex(&state_mutex, plugin_state);
release_mutex(&state_mutex, plugin_state_m);
}
view_port_enabled_set(view_port, false);

View File

@ -19,10 +19,10 @@ typedef struct {
float timezone_offset;
ListNode* tokens_list;
bool token_list_loaded;
uint8_t tokens_count;
uint16_t tokens_count;
uint8_t* crypto_verify_data;
uint8_t crypto_verify_data_length;
size_t crypto_verify_data_length;
bool pin_set;
uint8_t iv[TOTP_IV_SIZE];
uint8_t base_iv[TOTP_IV_SIZE];

View File

@ -5,9 +5,11 @@
#include "common.h"
#include "../services/base32/base32.h"
#include "../services/crypto/crypto.h"
#include "../services/crypto/memset_s.h"
TokenInfo* token_info_alloc() {
TokenInfo* tokenInfo = malloc(sizeof(TokenInfo));
furi_check(tokenInfo != NULL);
tokenInfo->algo = SHA1;
tokenInfo->digits = TOTP_6_DIGITS;
return tokenInfo;
@ -23,11 +25,12 @@ void token_info_free(TokenInfo* token_info) {
bool token_info_set_secret(
TokenInfo* token_info,
const char* base32_token_secret,
uint8_t token_secret_length,
uint8_t* iv) {
size_t token_secret_length,
const uint8_t* iv) {
uint8_t* plain_secret = malloc(token_secret_length);
furi_check(plain_secret != NULL);
int plain_secret_length =
base32_decode((uint8_t*)base32_token_secret, plain_secret, token_secret_length);
base32_decode((const uint8_t*)base32_token_secret, plain_secret, token_secret_length);
bool result;
if(plain_secret_length >= 0) {
token_info->token =
@ -37,17 +40,19 @@ bool token_info_set_secret(
result = false;
}
memset(plain_secret, 0, token_secret_length);
memset_s(plain_secret, token_secret_length, 0, token_secret_length);
free(plain_secret);
return result;
}
uint8_t token_info_get_digits_count(TokenInfo* token_info) {
uint8_t token_info_get_digits_count(const TokenInfo* token_info) {
switch(token_info->digits) {
case TOTP_6_DIGITS:
return 6;
case TOTP_8_DIGITS:
return 8;
default:
break;
}
return 6;

View File

@ -8,7 +8,7 @@ typedef enum { TOTP_6_DIGITS, TOTP_8_DIGITS } TokenDigitsCount;
typedef struct {
uint8_t* token;
uint8_t token_length;
size_t token_length;
char* name;
TokenHashAlgo algo;
TokenDigitsCount digits;
@ -19,6 +19,6 @@ void token_info_free(TokenInfo* token_info);
bool token_info_set_secret(
TokenInfo* token_info,
const char* base32_token_secret,
uint8_t token_secret_length,
uint8_t* iv);
uint8_t token_info_get_digits_count(TokenInfo* token_info);
size_t token_secret_length,
const uint8_t* iv);
uint8_t token_info_get_digits_count(const TokenInfo* token_info);