Skip to content

Commit

Permalink
Fixing SONAR issues (#13)
Browse files Browse the repository at this point in the history
* Secure cleanup of FuriString holding token secret in CLI
* Few refactoring
* Working on SONAR issues
  • Loading branch information
akopachov authored Oct 28, 2022
1 parent 8d7167c commit a5fcc23
Show file tree
Hide file tree
Showing 18 changed files with 154 additions and 72 deletions.
18 changes: 16 additions & 2 deletions scenes/add_new_token/totp_input_text.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -32,10 +42,14 @@ 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);
result->user_input_length =
strnlen(text_input_state->text_input_buffer, INPUT_BUFFER_SIZE);
result->user_input = malloc(result->user_input_length + 1);
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);
}
}
Expand Down
2 changes: 1 addition & 1 deletion scenes/add_new_token/totp_input_text.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

typedef struct {
char* user_input;
uint8_t user_input_length;
size_t user_input_length;
void* callback_data;
} InputTextSceneCallbackResult;

Expand Down
9 changes: 6 additions & 3 deletions scenes/add_new_token/totp_scene_add_new_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ 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;
Expand Down Expand Up @@ -235,7 +235,10 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState

if(token_secret_set) {
tokenInfo->name = malloc(scene_state->token_name_length + 1);
strcpy(tokenInfo->name, scene_state->token_name);
strlcpy(
tokenInfo->name,
scene_state->token_name,
scene_state->token_name_length + 1);
tokenInfo->algo = scene_state->algo;
tokenInfo->digits = scene_state->digits_count;

Expand Down
14 changes: 8 additions & 6 deletions scenes/generate_token/totp_scene_generate_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "../../services/totp/totp.h"
#include "../../services/config/config.h"
#include "../../services/crypto/crypto.h"
#include "../../services/crypto/memset_s.h"
#include "../scene_director.h"
#include "../token_menu/totp_scene_token_menu.h"

Expand Down Expand Up @@ -95,7 +96,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);
}

Expand Down Expand Up @@ -180,7 +181,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);

Expand All @@ -195,7 +196,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, sizeof(key), 0, key_length);
free(key);
} else {
i_token_to_str(0, scene_state->last_code, tokenInfo->digits);
Expand Down Expand Up @@ -265,7 +266,9 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
}
}

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) {
if(event->type == EventTypeKey) {
if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) {
return false;
Expand Down Expand Up @@ -314,11 +317,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);
}
8 changes: 5 additions & 3 deletions scenes/generate_token/totp_scene_generate_token.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ typedef struct {
uint8_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);
1 change: 0 additions & 1 deletion services/cli/cli_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli) {
}

TOTP_CLI_DELETE_LAST_LINE();
fflush(stdout);

if(plugin_state->current_scene == TotpSceneAuthentication) {
return false;
Expand Down
28 changes: 20 additions & 8 deletions services/cli/cli_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,26 @@
#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_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_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_PRINT_INVALID_ARGUMENTS() \
TOTP_CLI_PRINTF( \
"Invalid command arguments. use \"help\" command to get list of available commands")
Expand Down
40 changes: 24 additions & 16 deletions services/cli/commands/add/add.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,16 @@ 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);
}

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
Expand All @@ -93,9 +99,9 @@ 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);
strlcpy(token_info->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1);

// Read optional arguments
bool mask_user_input = true;
Expand Down Expand Up @@ -146,13 +152,15 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
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");
furi_string_free(temp_str);
TOTP_CLI_PRINTF("Cancelled by user\r\n");
furi_string_secure_free(temp_str);
token_info_free(token_info);
return;
} else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
Expand All @@ -166,8 +174,7 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
} 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);
TOTP_CLI_DELETE_LAST_CHAR();
furi_string_left(temp_str, temp_str_size - 1);
}
} else if(c == CliSymbolAsciiCR) {
Expand All @@ -176,25 +183,26 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
}
}

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);
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) {
Expand Down
12 changes: 7 additions & 5 deletions services/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,9 @@ 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 = (char*)malloc(temp_cstr_len + 1);
strlcpy(tokenInfo->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1);

uint32_t secret_bytes_count;
if(!flipper_format_get_value_count(
Expand All @@ -355,9 +355,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;
Expand Down
15 changes: 8 additions & 7 deletions services/crypto/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -11,13 +12,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* 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);
memset(plain_data_aligned, 0, plain_data_aligned_length);
memcpy(plain_data_aligned, plain_data, plain_data_length);
Expand All @@ -29,7 +30,7 @@ uint8_t* totp_crypto_encrypt(
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, sizeof(plain_data_aligned), 0, plain_data_aligned_length);
free(plain_data_aligned);
} else {
encrypted_data = malloc(plain_data_length);
Expand All @@ -45,9 +46,9 @@ 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_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
Expand Down Expand Up @@ -118,7 +119,7 @@ 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;
size_t decrypted_key_length;
uint8_t* decrypted_key = totp_crypto_decrypt(
plugin_state->crypto_verify_data,
plugin_state->crypto_verify_data_length,
Expand Down
8 changes: 4 additions & 4 deletions services/crypto/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
size_t* decrypted_data_length);
void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length);
bool totp_crypto_verify_key(const PluginState* plugin_state);
Loading

0 comments on commit a5fcc23

Please sign in to comment.