MX 2022-11-24 01:19:19 +03:00
parent 2c51c8cb31
commit b6435374d7
No known key found for this signature in database
GPG Key ID: 6C4C311DFD4B4AB5
68 changed files with 877 additions and 381 deletions

View File

@ -16,5 +16,22 @@ App(
order=20,
fap_category="Misc",
fap_icon_assets="images",
fap_icon="totp_10px.png"
fap_icon="totp_10px.png",
fap_private_libs=[
Lib(
name="base32",
),
Lib(
name="list",
),
Lib(
name="timezone_utils",
),
Lib(
name="polyfills",
),
Lib(
name="roll_value",
),
],
)

View File

@ -9,6 +9,8 @@
#include "commands/timezone/timezone.h"
#include "commands/help/help.h"
#include "commands/move/move.h"
#include "commands/pin/pin.h"
#include "commands/notification/notification.h"
static void totp_cli_print_unknown_command(const FuriString* unknown_command) {
TOTP_CLI_PRINTF(
@ -49,6 +51,10 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_MOVE) == 0 ||
furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_MOVE_ALT) == 0) {
totp_cli_command_move_handle(plugin_state, args, cli);
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_PIN) == 0) {
totp_cli_command_pin_handle(plugin_state, args, cli);
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_NOTIFICATION) == 0) {
totp_cli_command_notification_handle(plugin_state, args, cli);
} else {
totp_cli_print_unknown_command(cmd);
}

View File

@ -1,7 +1,7 @@
#pragma once
#include <cli/cli.h>
#include "../../types/plugin_state.h"
#include "../types/plugin_state.h"
void totp_cli_register_command_handler(PluginState* plugin_state);
void totp_cli_unregister_command_handler();

View File

@ -1,11 +1,12 @@
#pragma once
#include <cli/cli.h>
#include "../../types/plugin_state.h"
#include "../types/plugin_state.h"
#define TOTP_CLI_COMMAND_NAME "totp"
#define DOCOPT_ARGUMENT(arg) "<" arg ">"
#define DOCOPT_MULTIPLE(arg) arg "..."
#define DOCOPT_OPTIONAL(param) "[" param "]"
#define DOCOPT_REQUIRED(param) "(" param ")"
#define DOCOPT_OPTION(option, value) option " " value
@ -37,4 +38,11 @@
TOTP_CLI_PRINTF( \
"Invalid command arguments. use \"help\" command to get list of available commands")
/**
* @brief Checks whether user is authenticated and entered correct PIN.
* If user is not authenticated it prompts user to enter correct PIN to authenticate.
* @param plugin_state application state
* @param cli reference to the firmware CLI subsystem
* @return \c true if user is already authenticated or successfully authenticated; \c false otherwise
*/
bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli);

View File

@ -1,11 +1,12 @@
#include "add.h"
#include <stdlib.h>
#include <lib/toolbox/args.h>
#include "../../../list/list.h"
#include "../../../../types/token_info.h"
#include "../../../config/config.h"
#include "../../../lib/list/list.h"
#include "../../../types/token_info.h"
#include "../../../services/config/config.h"
#include "../../../services/convert/convert.h"
#include "../../cli_helpers.h"
#include "../../../../scenes/scene_director.h"
#include "../../../ui/scene_director.h"
#define TOTP_CLI_COMMAND_ADD_ARG_NAME "name"
#define TOTP_CLI_COMMAND_ADD_ARG_ALGO "algo"
@ -14,21 +15,6 @@
#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, const FuriString* str) {
switch(furi_string_get_char(str, 0)) {
case '6':
token_info->digits = TOTP_6_DIGITS;
return true;
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, const FuriString* str) {
if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) {
token_info->algo = SHA1;
@ -73,6 +59,7 @@ void totp_cli_command_add_docopt_options() {
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_ALGO)) " Token hashing algorithm.\r\n");
TOTP_CLI_PRINTF(
" Could be one of: sha1, sha256, sha512 " DOCOPT_DEFAULT("sha1") "\r\n");
cli_nl();
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX,
DOCOPT_ARGUMENT(
@ -94,7 +81,7 @@ static bool totp_cli_read_secret(Cli* cli, FuriString* out_str, bool mask_user_i
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
// We need to ignore them as we care about alpha-numerics only
uint8_t c2;
cli_read_timeout(cli, &c2, 1, 0);
cli_read_timeout(cli, &c2, 1, 0);
@ -164,7 +151,8 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
TOTP_CLI_PRINTF(
"Missed value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX
"\"\r\n");
} else if(!token_info_set_digits_from_str(token_info, temp_str)) {
} else if(!token_info_set_digits_from_int(
token_info, CONVERT_CHAR_TO_DIGIT(furi_string_get_char(temp_str, 0)))) {
TOTP_CLI_PRINTF(
"\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX
"\"\r\n",

View File

@ -1,7 +1,7 @@
#pragma once
#include <cli/cli.h>
#include "../../../../types/plugin_state.h"
#include "../../../types/plugin_state.h"
#define TOTP_CLI_COMMAND_ADD "add"
#define TOTP_CLI_COMMAND_ADD_ALT "mk"

View File

@ -3,10 +3,10 @@
#include <stdlib.h>
#include <ctype.h>
#include <lib/toolbox/args.h>
#include "../../../list/list.h"
#include "../../../config/config.h"
#include "../../../lib/list/list.h"
#include "../../../services/config/config.h"
#include "../../cli_helpers.h"
#include "../../../../scenes/scene_director.h"
#include "../../../ui/scene_director.h"
#define TOTP_CLI_COMMAND_DELETE_ARG_INDEX "index"
#define TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX "-f"

View File

@ -1,7 +1,7 @@
#pragma once
#include <cli/cli.h>
#include "../../../../types/plugin_state.h"
#include "../../../types/plugin_state.h"
#define TOTP_CLI_COMMAND_DELETE "delete"
#define TOTP_CLI_COMMAND_DELETE_ALT "rm"

View File

@ -5,6 +5,8 @@
#include "../list/list.h"
#include "../timezone/timezone.h"
#include "../move/move.h"
#include "../pin/pin.h"
#include "../notification/notification.h"
void totp_cli_command_help_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT
@ -25,6 +27,8 @@ void totp_cli_command_help_handle() {
totp_cli_command_delete_docopt_usage();
totp_cli_command_timezone_docopt_usage();
totp_cli_command_move_docopt_usage();
totp_cli_command_pin_docopt_usage();
totp_cli_command_notification_docopt_usage();
cli_nl();
TOTP_CLI_PRINTF("Commands:\r\n");
totp_cli_command_help_docopt_commands();
@ -33,11 +37,14 @@ void totp_cli_command_help_handle() {
totp_cli_command_delete_docopt_commands();
totp_cli_command_timezone_docopt_commands();
totp_cli_command_move_docopt_commands();
totp_cli_command_pin_docopt_commands();
totp_cli_command_notification_docopt_commands();
cli_nl();
TOTP_CLI_PRINTF("Arguments:\r\n");
totp_cli_command_add_docopt_arguments();
totp_cli_command_delete_docopt_arguments();
totp_cli_command_timezone_docopt_arguments();
totp_cli_command_notification_docopt_arguments();
cli_nl();
TOTP_CLI_PRINTF("Options:\r\n");
totp_cli_command_add_docopt_options();

View File

@ -1,8 +1,8 @@
#include "list.h"
#include <stdlib.h>
#include "../../../list/list.h"
#include "../../../../types/token_info.h"
#include "../../../config/constants.h"
#include "../../../lib/list/list.h"
#include "../../../types/token_info.h"
#include "../../../services/config/constants.h"
#include "../../cli_helpers.h"
static char* get_algo_as_cstr(TokenHashAlgo algo) {
@ -20,19 +20,6 @@ static char* get_algo_as_cstr(TokenHashAlgo algo) {
return "UNKNOWN";
}
static uint8_t get_digits_as_int(TokenDigitsCount digits) {
switch(digits) {
case TOTP_6_DIGITS:
return 6;
case TOTP_8_DIGITS:
return 8;
default:
break;
}
return 6;
}
void totp_cli_command_list_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_LIST ", " TOTP_CLI_COMMAND_LIST_ALT
" List all available tokens\r\n");
@ -53,23 +40,19 @@ void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) {
return;
}
ListNode* node = plugin_state->tokens_list;
TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n");
TOTP_CLI_PRINTF("| %-*s | %-*s | %-*s | %-s |\r\n", 3, "#", 27, "Name", 6, "Algo", "Digits");
TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n");
uint16_t index = 1;
while(node != NULL) {
TOTP_LIST_FOREACH(plugin_state->tokens_list, node, {
TokenInfo* token_info = (TokenInfo*)node->data;
token_info_get_digits_count(token_info);
TOTP_CLI_PRINTF(
"| %-3" PRIu16 " | %-27.27s | %-6s | %-6" PRIu8 " |\r\n",
index,
token_info->name,
get_algo_as_cstr(token_info->algo),
get_digits_as_int(token_info->digits));
node = node->next;
token_info->digits);
index++;
}
});
TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n");
}

View File

@ -1,7 +1,7 @@
#pragma once
#include <cli/cli.h>
#include "../../../../types/plugin_state.h"
#include "../../../types/plugin_state.h"
#define TOTP_CLI_COMMAND_LIST "list"
#define TOTP_CLI_COMMAND_LIST_ALT "ls"

View File

@ -2,11 +2,11 @@
#include <stdlib.h>
#include <lib/toolbox/args.h>
#include "../../../list/list.h"
#include "../../../../types/token_info.h"
#include "../../../config/config.h"
#include "../../../lib/list/list.h"
#include "../../../types/token_info.h"
#include "../../../services/config/config.h"
#include "../../cli_helpers.h"
#include "../../../../scenes/scene_director.h"
#include "../../../ui/scene_director.h"
#define TOTP_CLI_COMMAND_MOVE_ARG_INDEX "index"

View File

@ -1,7 +1,7 @@
#pragma once
#include <cli/cli.h>
#include "../../../../types/plugin_state.h"
#include "../../../types/plugin_state.h"
#define TOTP_CLI_COMMAND_MOVE "move"
#define TOTP_CLI_COMMAND_MOVE_ALT "mv"

View File

@ -0,0 +1,106 @@
#include "notification.h"
#include <lib/toolbox/args.h>
#include "../../../services/config/config.h"
#include "../../../ui/scene_director.h"
#include "../../cli_helpers.h"
#define TOTP_CLI_COMMAND_NOTIFICATION_ARG_METHOD "method"
#define TOTP_CLI_COMMAND_NOTIFICATION_METHOD_NONE "none"
#define TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND "sound"
#define TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO "vibro"
void totp_cli_command_notification_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NOTIFICATION
" Get or set notification method\r\n");
}
void totp_cli_command_notification_docopt_usage() {
TOTP_CLI_PRINTF(
" " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_NOTIFICATION " " DOCOPT_OPTIONAL(
DOCOPT_MULTIPLE(DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_NOTIFICATION_ARG_METHOD))) "\r\n");
}
void totp_cli_command_notification_docopt_arguments() {
TOTP_CLI_PRINTF(
" " TOTP_CLI_COMMAND_NOTIFICATION_ARG_METHOD
" Notification method to be set. Must be one of [" TOTP_CLI_COMMAND_NOTIFICATION_METHOD_NONE
", " TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND
", " TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO "]\r\n");
}
static void totp_cli_command_notification_print_method(NotificationMethod method) {
bool has_previous_method = false;
if(method & NotificationMethodSound) {
TOTP_CLI_PRINTF("\"" TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND "\"");
has_previous_method = true;
}
if(method & NotificationMethodVibro) {
if(has_previous_method) {
TOTP_CLI_PRINTF(" and ");
}
TOTP_CLI_PRINTF("\"" TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO "\"");
}
if(method == NotificationMethodNone) {
TOTP_CLI_PRINTF("\"" TOTP_CLI_COMMAND_NOTIFICATION_METHOD_NONE "\"");
}
}
void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
return;
}
FuriString* temp_str = furi_string_alloc();
bool new_method_provided = false;
NotificationMethod new_method = NotificationMethodNone;
bool args_valid = true;
while(args_read_string_and_trim(args, temp_str)) {
if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_NOTIFICATION_METHOD_NONE) == 0) {
new_method_provided = true;
new_method = NotificationMethodNone;
} else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND) == 0) {
new_method_provided = true;
new_method |= NotificationMethodSound;
} else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO) == 0) {
new_method_provided = true;
new_method |= NotificationMethodVibro;
} else {
args_valid = false;
break;
}
}
do {
if(!args_valid) {
TOTP_CLI_PRINT_INVALID_ARGUMENTS();
break;
}
if(new_method_provided) {
Scene previous_scene = TotpSceneNone;
if(plugin_state->current_scene == TotpSceneGenerateToken ||
plugin_state->current_scene == TotpSceneAppSettings) {
previous_scene = plugin_state->current_scene;
totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);
}
plugin_state->notification_method = new_method;
totp_config_file_update_notification_method(new_method);
if(previous_scene != TotpSceneNone) {
totp_scene_director_activate_scene(plugin_state, previous_scene, NULL);
}
TOTP_CLI_PRINTF("Notification method is set to ");
totp_cli_command_notification_print_method(new_method);
cli_nl();
} else {
TOTP_CLI_PRINTF("Current notification method is ");
totp_cli_command_notification_print_method(plugin_state->notification_method);
cli_nl();
}
} while(false);
furi_string_free(temp_str);
}

View File

@ -0,0 +1,11 @@
#pragma once
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#define TOTP_CLI_COMMAND_NOTIFICATION "notify"
void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
void totp_cli_command_notification_docopt_commands();
void totp_cli_command_notification_docopt_usage();
void totp_cli_command_notification_docopt_arguments();

View File

@ -0,0 +1,172 @@
#include "pin.h"
#include <stdlib.h>
#include <lib/toolbox/args.h>
#include "../../../types/token_info.h"
#include "../../../types/user_pin_codes.h"
#include "../../../services/config/config.h"
#include "../../cli_helpers.h"
#include "../../../lib/polyfills/memset_s.h"
#include "../../../services/crypto/crypto.h"
#include "../../../ui/scene_director.h"
#define TOTP_CLI_COMMAND_PIN_COMMAND_SET "set"
#define TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE "remove"
void totp_cli_command_pin_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_PIN " Set\\change\\remove PIN\r\n");
}
void totp_cli_command_pin_docopt_usage() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_PIN " " DOCOPT_REQUIRED(
TOTP_CLI_COMMAND_PIN_COMMAND_SET " | " TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE) "\r\n");
}
static inline uint8_t totp_cli_key_to_pin_code(uint8_t key) {
uint8_t code = 0;
switch(key) {
case 0x44: // left
code = PinCodeArrowLeft;
break;
case 0x41: // up
code = PinCodeArrowUp;
break;
case 0x43: // right
code = PinCodeArrowRight;
break;
case 0x42: // down
code = PinCodeArrowDown;
break;
default:
break;
}
return code;
}
static bool totp_cli_read_pin(Cli* cli, uint8_t* pin, uint8_t* pin_length) {
TOTP_CLI_PRINTF("Enter new PIN (use arrow keys on your keyboard): ");
fflush(stdout);
uint8_t c;
*pin_length = 0;
while(cli_read(cli, &c, 1) == 1) {
if(c == CliSymbolAsciiEsc) {
uint8_t c2;
uint8_t c3;
if(cli_read_timeout(cli, &c2, 1, 0) == 1 && cli_read_timeout(cli, &c3, 1, 0) == 1 &&
c2 == 0x5b) {
uint8_t code = totp_cli_key_to_pin_code(c3);
if(code > 0) {
pin[*pin_length] = code;
*pin_length = *pin_length + 1;
putc('*', stdout);
fflush(stdout);
}
}
} else if(c == CliSymbolAsciiETX) {
TOTP_CLI_DELETE_CURRENT_LINE();
TOTP_CLI_PRINTF("Cancelled by user\r\n");
return false;
} else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
if(*pin_length > 0) {
*pin_length = *pin_length - 1;
pin[*pin_length] = 0;
TOTP_CLI_DELETE_LAST_CHAR();
}
} else if(c == CliSymbolAsciiCR) {
cli_nl();
break;
}
}
TOTP_CLI_DELETE_LAST_LINE();
return true;
}
void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
UNUSED(plugin_state);
FuriString* temp_str = furi_string_alloc();
bool do_change = false;
bool do_remove = false;
UNUSED(do_remove);
if(args_read_string_and_trim(args, temp_str)) {
if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_SET) == 0) {
do_change = true;
} else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_PIN_COMMAND_REMOVE) == 0) {
do_remove = true;
} else {
TOTP_CLI_PRINT_INVALID_ARGUMENTS();
}
} else {
TOTP_CLI_PRINT_INVALID_ARGUMENTS();
}
if((do_change || do_remove) && totp_cli_ensure_authenticated(plugin_state, cli)) {
bool load_generate_token_scene = false;
do {
uint8_t old_iv[TOTP_IV_SIZE];
memcpy(&old_iv[0], &plugin_state->iv[0], TOTP_IV_SIZE);
uint8_t new_pin[TOTP_IV_SIZE];
uint8_t new_pin_length = 0;
if(do_change) {
if(!totp_cli_read_pin(cli, &new_pin[0], &new_pin_length) ||
!totp_cli_ensure_authenticated(plugin_state, cli)) {
memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE);
break;
}
} else if(do_remove) {
new_pin_length = 0;
memset(&new_pin[0], 0, TOTP_IV_SIZE);
}
if(plugin_state->current_scene == TotpSceneGenerateToken) {
totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);
load_generate_token_scene = true;
}
TOTP_CLI_PRINTF("Encrypting, please wait...\r\n");
memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE);
memset(&plugin_state->base_iv[0], 0, TOTP_IV_SIZE);
if(plugin_state->crypto_verify_data != NULL) {
free(plugin_state->crypto_verify_data);
plugin_state->crypto_verify_data = NULL;
}
totp_crypto_seed_iv(
plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length);
TOTP_LIST_FOREACH(plugin_state->tokens_list, node, {
TokenInfo* token_info = node->data;
size_t plain_token_length;
uint8_t* plain_token = totp_crypto_decrypt(
token_info->token, token_info->token_length, &old_iv[0], &plain_token_length);
free(token_info->token);
token_info->token = totp_crypto_encrypt(
plain_token,
plain_token_length,
&plugin_state->iv[0],
&token_info->token_length);
memset_s(plain_token, plain_token_length, 0, plain_token_length);
free(plain_token);
});
totp_full_save_config_file(plugin_state);
TOTP_CLI_DELETE_LAST_LINE();
if(do_change) {
TOTP_CLI_PRINTF("PIN has been successfully changed\r\n");
} else if(do_remove) {
TOTP_CLI_PRINTF("PIN has been successfully removed\r\n");
}
} while(false);
if(load_generate_token_scene) {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
}
furi_string_free(temp_str);
}

View File

@ -0,0 +1,10 @@
#pragma once
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#define TOTP_CLI_COMMAND_PIN "pin"
void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
void totp_cli_command_pin_docopt_commands();
void totp_cli_command_pin_docopt_usage();

View File

@ -1,7 +1,7 @@
#include "timezone.h"
#include <lib/toolbox/args.h>
#include "../../../config/config.h"
#include "../../../../scenes/scene_director.h"
#include "../../../services/config/config.h"
#include "../../../ui/scene_director.h"
#include "../../cli_helpers.h"
#define TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE "timezone"
@ -21,8 +21,6 @@ void totp_cli_command_timezone_docopt_usage() {
void totp_cli_command_timezone_docopt_arguments() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE
" Timezone offset in hours to be set.\r\n");
TOTP_CLI_PRINTF(
" If not provided then current timezone offset will be printed\r\n");
}
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {

View File

@ -1,7 +1,7 @@
#pragma once
#include <cli/cli.h>
#include "../../../../types/plugin_state.h"
#include "../../../types/plugin_state.h"
#define TOTP_CLI_COMMAND_TIMEZONE "timezone"
#define TOTP_CLI_COMMAND_TIMEZONE_ALT "tz"

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

View File

@ -92,3 +92,11 @@ void list_free(ListNode* head);
assert(list_add(head, item) != NULL); \
} \
} while(false)
#define TOTP_LIST_FOREACH(head, node, action) \
do { \
ListNode* node = head; \
while(node != NULL) { \
action node = node->next; \
} \
} while(false)

View File

@ -0,0 +1,11 @@
#include "strnlen.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;
}

View File

@ -0,0 +1,3 @@
#include <stddef.h>
size_t strnlen(const char* s, size_t maxlen);

View File

@ -2,7 +2,9 @@
#include <stdint.h>
typedef enum {
typedef uint8_t TotpRollValueOverflowBehavior;
enum TotpRollValueOverflowBehaviors {
/**
* @brief Do not change value if it reached constraint
*/
@ -12,7 +14,7 @@ typedef enum {
* @brief Set value to opposite constraint value if it reached constraint
*/
RollOverflowBehaviorRoll
} TotpRollValueOverflowBehavior;
};
#define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \
void totp_roll_value_##type( \

View File

@ -10,32 +10,6 @@
#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(const TokenInfo* token_info) {
switch(token_info->digits) {
case TOTP_6_DIGITS:
return 6;
case TOTP_8_DIGITS:
return 8;
default:
break;
}
return 6;
}
static void token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) {
switch(digits) {
case 6:
token_info->digits = TOTP_6_DIGITS;
break;
case 8:
token_info->digits = TOTP_8_DIGITS;
break;
default:
break;
}
}
static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) {
switch(token_info->algo) {
case SHA1:
@ -106,6 +80,15 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
fff_data_file,
"Timezone offset in hours. Important note: do not put '+' sign for positive values");
flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &tmp_tz, 1);
uint32_t tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
flipper_format_write_comment_cstr(fff_data_file, " ");
flipper_format_write_comment_cstr(
fff_data_file,
"How to notify user when new token is generated or badusb mode is activated (possible values: 0 - do not notify, 1 - sound, 2 - vibro, 3 sound and vibro)");
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1);
FuriString* temp_str = furi_string_alloc();
flipper_format_write_comment_cstr(fff_data_file, " ");
@ -172,8 +155,8 @@ void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* tok
}
flipper_format_write_string_cstr(
file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info));
uint32_t digits_count_as_uint32 = token_info_get_digits_as_int(token_info);
flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &digits_count_as_uint32, 1);
uint32_t tmp_uint32 = token_info->digits;
flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1);
}
void totp_config_file_save_new_token(const TokenInfo* token_info) {
@ -196,6 +179,32 @@ void totp_config_file_update_timezone_offset(float new_timezone_offset) {
totp_close_storage();
}
void totp_config_file_update_notification_method(NotificationMethod new_notification_method) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file = totp_open_config_file(cfg_storage);
uint32_t tmp_uint32 = new_notification_method;
flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1);
totp_close_config_file(file);
totp_close_storage();
}
void totp_config_file_update_user_settings(const PluginState* plugin_state) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file = totp_open_config_file(cfg_storage);
flipper_format_insert_or_update_float(
file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1);
uint32_t tmp_uint32 = plugin_state->notification_method;
flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1);
totp_close_config_file(file);
totp_close_storage();
}
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);
@ -213,12 +222,14 @@ void totp_full_save_config_file(const PluginState* const plugin_state) {
flipper_format_write_float(
fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1);
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) {
uint32_t tmp_uint32 = plugin_state->notification_method;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1);
TOTP_LIST_FOREACH(plugin_state->tokens_list, node, {
const TokenInfo* token_info = node->data;
totp_config_file_save_new_token_i(fff_data_file, token_info);
node = node->next;
}
});
totp_close_config_file(fff_data_file);
totp_close_storage();
@ -321,6 +332,16 @@ void totp_config_file_load_base(PluginState* const plugin_state) {
plugin_state->pin_set = true;
}
flipper_format_rewind(fff_data_file);
uint32_t tmp_uint32;
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
}
plugin_state->notification_method = tmp_uint32;
furi_string_free(temp_str);
totp_close_config_file(fff_data_file);
totp_close_storage();
@ -409,10 +430,9 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
tokenInfo->algo = SHA1;
}
if(flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1)) {
token_info_set_digits_from_int(tokenInfo, temp_data32);
} else {
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1) ||
!token_info_set_digits_from_int(tokenInfo, temp_data32)) {
tokenInfo->digits = TOTP_6_DIGITS;
}

View File

@ -6,10 +6,12 @@
#include "../../types/token_info.h"
#include "constants.h"
typedef uint8_t TokenLoadingResult;
/**
* @brief Token loading results
*/
typedef enum {
enum TokenLoadingResults {
/**
* @brief All the tokens loaded successfully
*/
@ -24,7 +26,7 @@ typedef enum {
* @brief Tokens not loaded because of error(s)
*/
TokenLoadingResultError
} TokenLoadingResult;
};
/**
* @brief Opens storage record
@ -80,3 +82,15 @@ void totp_config_file_save_new_token(const TokenInfo* token_info);
* @param new_timezone_offset new timezone offset to be set
*/
void totp_config_file_update_timezone_offset(float new_timezone_offset);
/**
* @brief Updates notification method in an application config file
* @param new_notification_method new notification method to be set
*/
void totp_config_file_update_notification_method(NotificationMethod new_notification_method);
/**
* @brief Updates application user settings
* @param plugin_state application state
*/
void totp_config_file_update_user_settings(const PluginState* plugin_state);

View File

@ -11,6 +11,7 @@
#define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto"
#define TOTP_CONFIG_KEY_BASE_IV "BaseIV"
#define TOTP_CONFIG_KEY_PINSET "PinIsSet"
#define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod"
#define TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME "sha1"
#define TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME "sha256"

View File

@ -0,0 +1,4 @@
#pragma once
#define CONVERT_DIGIT_TO_CHAR(digit) ((digit) + '0')
#define CONVERT_CHAR_TO_DIGIT(ch) ((ch) - '0')

View File

@ -1,23 +0,0 @@
#pragma once
#include <stdlib.h>
#include <furi/furi.h>
#include <furi_hal.h>
typedef struct {
char* string;
uint8_t string_length;
FuriThread* thread;
FuriMutex* string_sync;
FuriHalUsbInterface* usb_mode_prev;
} TotpHidWorkerTypeContext;
typedef enum {
TotpHidWorkerEvtReserved = (1 << 0),
TotpHidWorkerEvtStop = (1 << 1),
TotpHidWorkerEvtType = (1 << 2)
} TotpHidWorkerEvtFlags;
TotpHidWorkerTypeContext* totp_hid_worker_start();
void totp_hid_worker_stop(TotpHidWorkerTypeContext* context);
void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event);

View File

@ -9,7 +9,7 @@
#include "../hmac/hmac_sha256.h"
#include "../hmac/hmac_sha512.h"
#include "../hmac/byteswap.h"
#include "../timezone_utils/timezone_utils.h"
#include "../../lib/timezone_utils/timezone_utils.h"
#define HMAC_MAX_SIZE 64

View File

@ -7,24 +7,22 @@
#include <flipper_format/flipper_format.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include "services/base32/base32.h"
#include "services/list/list.h"
#include "services/config/config.h"
#include "types/plugin_state.h"
#include "types/token_info.h"
#include "types/plugin_event.h"
#include "types/event_type.h"
#include "types/common.h"
#include "scenes/scene_director.h"
#include "services/ui/constants.h"
#include "ui/scene_director.h"
#include "ui/constants.h"
#include "services/crypto/crypto.h"
#include "services/cli/cli.h"
#include "cli/cli.h"
#define IDLE_TIMEOUT 60000
static void render_callback(Canvas* const canvas, void* ctx) {
PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25);
if(plugin_state != NULL && !plugin_state->changing_scene) {
if(plugin_state != NULL) {
totp_scene_director_render(canvas, plugin_state);
}
@ -40,8 +38,8 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu
static bool totp_plugin_state_init(PluginState* const plugin_state) {
plugin_state->gui = furi_record_open(RECORD_GUI);
plugin_state->notification = furi_record_open(RECORD_NOTIFICATION);
plugin_state->dialogs = furi_record_open(RECORD_DIALOGS);
plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION);
plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS);
totp_config_file_load_base(plugin_state);
@ -59,7 +57,8 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) {
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
DialogMessageButton dialog_result = dialog_message_show(plugin_state->dialogs, message);
DialogMessageButton dialog_result =
dialog_message_show(plugin_state->dialogs_app, message);
dialog_message_free(message);
if(dialog_result == DialogMessageButtonRight) {
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
@ -86,7 +85,7 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) {
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
dialog_message_show(plugin_state->dialogs, message);
dialog_message_show(plugin_state->dialogs_app, message);
dialog_message_free(message);
return false;
}
@ -152,7 +151,6 @@ int32_t totp_app() {
bool processing = true;
uint32_t last_user_interaction_time = furi_get_tick();
while(processing) {
if(plugin_state->changing_scene) continue;
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state_m = acquire_mutex_block(&state_mutex);

View File

@ -1,7 +1,9 @@
#pragma once
#include <inttypes.h>
typedef enum {
typedef uint8_t EventType;
enum EventTypes {
EventTypeTick,
EventTypeKey,
} EventType;
};

View File

@ -0,0 +1,9 @@
#pragma once
typedef uint8_t NotificationMethod;
enum NotificationMethods {
NotificationMethodNone = 0b00,
NotificationMethodSound = 0b01,
NotificationMethodVibro = 0b10,
};

View File

@ -3,8 +3,9 @@
#include <notification/notification.h>
#include <gui/gui.h>
#include <dialogs/dialogs.h>
#include "../services/list/list.h"
#include "../scenes/totp_scenes_enum.h"
#include "../lib/list/list.h"
#include "../ui/totp_scenes_enum.h"
#include "notification_method.h"
#define TOTP_IV_SIZE 16
@ -22,20 +23,15 @@ typedef struct {
*/
void* current_scene_state;
/**
* @brief Whether scene is changing now
*/
bool changing_scene;
/**
* @brief Reference to the firmware notification subsystem
*/
NotificationApp* notification;
NotificationApp* notification_app;
/**
* @brief Reference to the firmware dialogs subsystem
*/
DialogsApp* dialogs;
DialogsApp* dialogs_app;
/**
* @brief Reference to the firmware GUI subsystem
@ -86,4 +82,9 @@ typedef struct {
* @brief Basic randomly-generated initialization vector (IV)
*/
uint8_t base_iv[TOTP_IV_SIZE];
/**
* @brief Notification method
*/
NotificationMethod notification_method;
} PluginState;

View File

@ -3,9 +3,9 @@
#include "token_info.h"
#include "stdlib.h"
#include "common.h"
#include "../services/base32/base32.h"
#include "../lib/base32/base32.h"
#include "../services/crypto/crypto.h"
#include "../services/crypto/memset_s.h"
#include "../lib/polyfills/memset_s.h"
TokenInfo* token_info_alloc() {
TokenInfo* tokenInfo = malloc(sizeof(TokenInfo));
@ -45,15 +45,17 @@ bool token_info_set_secret(
return result;
}
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;
bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) {
switch(digits) {
case 6:
token_info->digits = TOTP_6_DIGITS;
return true;
case 8:
token_info->digits = TOTP_8_DIGITS;
return true;
default:
break;
}
return 6;
return false;
}

View File

@ -2,10 +2,13 @@
#include <inttypes.h>
typedef uint8_t TokenHashAlgo;
typedef uint8_t TokenDigitsCount;
/**
* @brief Hashing algorithm to be used to generate token
*/
typedef enum {
enum TokenHashAlgos {
/**
* @brief SHA1 hashing algorithm
*/
@ -20,22 +23,22 @@ typedef enum {
* @brief SHA512 hashing algorithm
*/
SHA512
} TokenHashAlgo;
};
/**
* @brief Token digits count to be generated.
*/
typedef enum {
enum TokenDigitsCounts {
/**
* @brief 6 digits
*/
TOTP_6_DIGITS,
TOTP_6_DIGITS = 6,
/**
* @brief 8 digits
*/
TOTP_8_DIGITS
} TokenDigitsCount;
TOTP_8_DIGITS = 8
};
#define TOTP_TOKEN_DIGITS_MAX_COUNT 8
@ -96,8 +99,9 @@ bool token_info_set_secret(
const uint8_t* iv);
/**
* @brief Gets token digits count as \c uint8_t type
* @param token_info instance which's desired digits count should be returned
* @return Token digits length as \c uint8_t type
* @brief Sets token digits count from \c uint8_t value
* @param token_info instance whichs token digits count length should be updated
* @param digits desired token digits count length
* @return \c true if token digits count length has been updated; \c false p
*/
uint8_t token_info_get_digits_count(const TokenInfo* token_info);
bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits);

View File

@ -0,0 +1,10 @@
#pragma once
typedef uint8_t TotpUserPinCode;
enum TotpUserPinCodes {
PinCodeArrowUp = 2,
PinCodeArrowRight = 8,
PinCodeArrowDown = 11,
PinCodeArrowLeft = 5
};

View File

@ -1,16 +1,15 @@
#include "../types/common.h"
#include "scene_director.h"
#include "authenticate/totp_scene_authenticate.h"
#include "generate_token/totp_scene_generate_token.h"
#include "add_new_token/totp_scene_add_new_token.h"
#include "token_menu/totp_scene_token_menu.h"
#include "app_settings/totp_app_settings.h"
#include "scenes/authenticate/totp_scene_authenticate.h"
#include "scenes/generate_token/totp_scene_generate_token.h"
#include "scenes/add_new_token/totp_scene_add_new_token.h"
#include "scenes/token_menu/totp_scene_token_menu.h"
#include "scenes/app_settings/totp_app_settings.h"
void totp_scene_director_activate_scene(
PluginState* const plugin_state,
Scene scene,
const void* context) {
plugin_state->changing_scene = true;
totp_scene_director_deactivate_active_scene(plugin_state);
switch(scene) {
case TotpSceneGenerateToken:
@ -35,7 +34,6 @@ void totp_scene_director_activate_scene(
}
plugin_state->current_scene = scene;
plugin_state->changing_scene = false;
}
void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state) {

View File

@ -1,16 +1,6 @@
#include "totp_input_text.h"
#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;
}
#include "../../../lib/polyfills/strnlen.h"
void view_draw(View* view, Canvas* canvas) {
furi_assert(view);

View File

@ -3,10 +3,8 @@
#include <gui/gui.h>
#include <gui/view.h>
#include <gui/modules/text_input.h>
#include <furi.h>
#include <furi_hal.h>
#include "../../types/plugin_state.h"
#include "../../types/plugin_event.h"
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
typedef struct {
char* user_input;

View File

@ -1,21 +1,19 @@
#include "totp_scene_add_new_token.h"
#include "../../types/common.h"
#include "../../services/ui/constants.h"
#include "../scene_director.h"
#include "../../../types/common.h"
#include "../../constants.h"
#include "../../scene_director.h"
#include "totp_input_text.h"
#include "../../types/token_info.h"
#include "../../services/list/list.h"
#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 "../../../types/token_info.h"
#include "../../../lib/list/list.h"
#include "../../../services/config/config.h"
#include "../../ui_controls.h"
#include "../../../lib/roll_value/roll_value.h"
#include "../../../types/nullable.h"
#include "../generate_token/totp_scene_generate_token.h"
#define TOKEN_ALGO_LIST_LENGTH 3
char* TOKEN_ALGO_LIST[] = {"SHA1", "SHA256", "SHA512"};
#define TOKEN_DIGITS_LIST_LENGTH 2
char* TOKEN_DIGITS_LIST[] = {"6 digits", "8 digits"};
char* TOKEN_DIGITS_TEXT_LIST[] = {"6 digits", "8 digits"};
TokenDigitsCount TOKEN_DIGITS_VALUE_LIST[] = {TOTP_6_DIGITS, TOTP_8_DIGITS};
typedef enum {
TokenNameTextBox,
@ -39,7 +37,7 @@ typedef struct {
TotpNullable_uint16_t current_token_index;
int16_t screen_y_offset;
TokenHashAlgo algo;
TokenDigitsCount digits_count;
uint8_t digits_count_index;
} SceneState;
void totp_scene_add_new_token_init(const PluginState* plugin_state) {
@ -127,7 +125,7 @@ void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_s
0,
63 - scene_state->screen_y_offset,
SCREEN_WIDTH,
TOKEN_DIGITS_LIST[scene_state->digits_count],
TOKEN_DIGITS_TEXT_LIST[scene_state->digits_count_index],
scene_state->selected_control == TokenLengthSelect);
ui_control_button_render(
canvas,
@ -197,11 +195,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
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);
&scene_state->digits_count_index, 1, 0, 1, RollOverflowBehaviorRoll);
}
break;
case InputKeyLeft:
@ -210,11 +204,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
&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);
&scene_state->digits_count_index, -1, 0, 1, RollOverflowBehaviorRoll);
}
break;
case InputKeyOk:
@ -253,7 +243,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
strlcpy(
tokenInfo->name, scene_state->token_name, scene_state->token_name_length + 1);
tokenInfo->algo = scene_state->algo;
tokenInfo->digits = scene_state->digits_count;
tokenInfo->digits = TOKEN_DIGITS_VALUE_LIST[scene_state->digits_count_index];
TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check);
plugin_state->tokens_count++;
@ -275,7 +265,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
dialog_message_show(plugin_state->dialogs, message);
dialog_message_show(plugin_state->dialogs_app, message);
dialog_message_free(message);
scene_state->selected_control = TokenSecretTextBox;
update_screen_y_offset(scene_state);

View File

@ -3,8 +3,8 @@
#include <gui/gui.h>
#include <furi.h>
#include <furi_hal.h>
#include "../../types/plugin_state.h"
#include "../../types/plugin_event.h"
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
typedef struct {
uint16_t current_token_index;

View File

@ -1,19 +1,25 @@
#include "totp_app_settings.h"
#include "../../services/ui/ui_controls.h"
#include "../scene_director.h"
#include <math.h>
#include <totp_icons.h>
#include "../../ui_controls.h"
#include "../../scene_director.h"
#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"
#include "../../constants.h"
#include "../../../services/config/config.h"
#include "../../../services/convert/convert.h"
#include "../../../lib/roll_value/roll_value.h"
#include "../../../types/nullable.h"
#define DIGIT_TO_CHAR(digit) ((digit) + '0')
char* YES_NO_LIST[] = {"NO", "YES"};
typedef enum { HoursInput, MinutesInput, ConfirmButton } Control;
typedef enum { HoursInput, MinutesInput, Sound, Vibro, ConfirmButton } Control;
typedef struct {
int8_t tz_offset_hours;
uint8_t tz_offset_minutes;
bool notification_sound;
bool notification_vibro;
uint8_t y_offset;
TotpNullable_uint16_t current_token_index;
Control selected_control;
} SceneState;
@ -38,55 +44,87 @@ void totp_scene_app_settings_activate(
float off_dec = modff(plugin_state->timezone_offset, &off_int);
scene_state->tz_offset_hours = off_int;
scene_state->tz_offset_minutes = 60.0f * off_dec;
scene_state->notification_sound = plugin_state->notification_method & NotificationMethodSound;
scene_state->notification_vibro = plugin_state->notification_method & NotificationMethodVibro;
}
static void two_digit_to_str(int8_t num, char* str) {
uint8_t index = 0;
if(num < 0) {
str[0] = '-';
index++;
str[index++] = '-';
num = -num;
}
uint8_t d1 = (num / 10) % 10;
uint8_t d2 = num % 10;
str[index] = DIGIT_TO_CHAR(d1);
str[index + 1] = DIGIT_TO_CHAR(d2);
str[index + 2] = '\0';
str[index++] = CONVERT_DIGIT_TO_CHAR(d1);
str[index++] = CONVERT_DIGIT_TO_CHAR(d2);
str[index++] = '\0';
}
void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state) {
const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plugin_state) {
const SceneState* scene_state = plugin_state->current_scene_state;
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Timezone offset");
canvas_draw_str_aligned(
canvas, 0, 0 - scene_state->y_offset, AlignLeft, AlignTop, "Timezone offset");
canvas_set_font(canvas, FontSecondary);
char tmp_str[4];
two_digit_to_str(scene_state->tz_offset_hours, &tmp_str[0]);
canvas_draw_str_aligned(canvas, 0, 16, AlignLeft, AlignTop, "Hours:");
canvas_draw_str_aligned(canvas, 0, 16 - scene_state->y_offset, AlignLeft, AlignTop, "Hours:");
ui_control_select_render(
canvas,
36,
10,
10 - scene_state->y_offset,
SCREEN_WIDTH - 36,
&tmp_str[0],
scene_state->selected_control == HoursInput);
two_digit_to_str(scene_state->tz_offset_minutes, &tmp_str[0]);
canvas_draw_str_aligned(canvas, 0, 34, AlignLeft, AlignTop, "Minutes:");
canvas_draw_str_aligned(
canvas, 0, 34 - scene_state->y_offset, AlignLeft, AlignTop, "Minutes:");
ui_control_select_render(
canvas,
36,
28,
28 - scene_state->y_offset,
SCREEN_WIDTH - 36,
&tmp_str[0],
scene_state->selected_control == MinutesInput);
canvas_draw_icon(
canvas,
SCREEN_WIDTH_CENTER - 5,
SCREEN_HEIGHT - 5 - scene_state->y_offset,
&I_totp_arrow_bottom_10x5);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(
canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 0, 80 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:");
ui_control_select_render(
canvas,
36,
74 - scene_state->y_offset,
SCREEN_WIDTH - 36,
YES_NO_LIST[scene_state->notification_sound],
scene_state->selected_control == Sound);
canvas_draw_str_aligned(canvas, 0, 98 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:");
ui_control_select_render(
canvas,
36,
92 - scene_state->y_offset,
SCREEN_WIDTH - 36,
YES_NO_LIST[scene_state->notification_vibro],
scene_state->selected_control == Vibro);
ui_control_button_render(
canvas,
SCREEN_WIDTH_CENTER - 24,
50,
115 - scene_state->y_offset,
48,
13,
"Confirm",
@ -113,10 +151,20 @@ bool totp_scene_app_settings_handle_event(
HoursInput,
ConfirmButton,
RollOverflowBehaviorStop);
if(scene_state->selected_control > MinutesInput) {
scene_state->y_offset = 64;
} else {
scene_state->y_offset = 0;
}
break;
case InputKeyDown:
totp_roll_value_uint8_t(
&scene_state->selected_control, 1, HoursInput, ConfirmButton, RollOverflowBehaviorStop);
if(scene_state->selected_control > MinutesInput) {
scene_state->y_offset = 64;
} else {
scene_state->y_offset = 0;
}
break;
case InputKeyRight:
if(scene_state->selected_control == HoursInput) {
@ -125,6 +173,10 @@ bool totp_scene_app_settings_handle_event(
} else if(scene_state->selected_control == MinutesInput) {
totp_roll_value_uint8_t(
&scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == Sound) {
scene_state->notification_sound = !scene_state->notification_sound;
} else if(scene_state->selected_control == Vibro) {
scene_state->notification_vibro = !scene_state->notification_vibro;
}
break;
case InputKeyLeft:
@ -134,13 +186,23 @@ bool totp_scene_app_settings_handle_event(
} else if(scene_state->selected_control == MinutesInput) {
totp_roll_value_uint8_t(
&scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == Sound) {
scene_state->notification_sound = !scene_state->notification_sound;
} else if(scene_state->selected_control == Vibro) {
scene_state->notification_vibro = !scene_state->notification_vibro;
}
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);
plugin_state->notification_method =
(scene_state->notification_sound ? NotificationMethodSound :
NotificationMethodNone) |
(scene_state->notification_vibro ? NotificationMethodVibro :
NotificationMethodNone);
totp_config_file_update_user_settings(plugin_state);
if(!scene_state->current_token_index.is_null) {
TokenMenuSceneContext generate_scene_context = {

View File

@ -1,10 +1,8 @@
#pragma once
#include <gui/gui.h>
#include <furi.h>
#include <furi_hal.h>
#include "../../types/plugin_state.h"
#include "../../types/plugin_event.h"
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
typedef struct {
uint16_t current_token_index;
@ -14,7 +12,7 @@ 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);
void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plugin_state);
bool totp_scene_app_settings_handle_event(
const PluginEvent* const event,
PluginState* plugin_state);

View File

@ -1,21 +1,18 @@
#include "totp_scene_authenticate.h"
#include <dialogs/dialogs.h>
#include <totp_icons.h>
#include "../../types/common.h"
#include "../../services/ui/constants.h"
#include "../../services/config/config.h"
#include "../scene_director.h"
#include "../totp_scenes_enum.h"
#include "../../services/crypto/crypto.h"
#include "../../../types/common.h"
#include "../../constants.h"
#include "../../../services/config/config.h"
#include "../../scene_director.h"
#include "../../totp_scenes_enum.h"
#include "../../../services/crypto/crypto.h"
#include "../../../types/user_pin_codes.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];
TotpUserPinCode code_input[MAX_CODE_LENGTH];
uint8_t code_length;
} SceneState;
@ -98,25 +95,25 @@ bool totp_scene_authenticate_handle_event(
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_input[scene_state->code_length] = PinCodeArrowUp;
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_input[scene_state->code_length] = PinCodeArrowDown;
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_input[scene_state->code_length] = PinCodeArrowRight;
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_input[scene_state->code_length] = PinCodeArrowLeft;
scene_state->code_length++;
}
break;
@ -142,7 +139,7 @@ bool totp_scene_authenticate_handle_event(
AlignCenter,
AlignCenter);
dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17);
dialog_message_show(plugin_state->dialogs, message);
dialog_message_show(plugin_state->dialogs_app, message);
dialog_message_free(message);
}
break;

View File

@ -1,10 +1,8 @@
#pragma once
#include <gui/gui.h>
#include <furi.h>
#include <furi_hal.h>
#include "../../types/plugin_state.h"
#include "../../types/plugin_event.h"
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
void totp_scene_authenticate_init(PluginState* plugin_state);
void totp_scene_authenticate_activate(PluginState* plugin_state);

View File

@ -3,20 +3,20 @@
#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/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 "../../../types/token_info.h"
#include "../../../types/common.h"
#include "../../constants.h"
#include "../../../services/totp/totp.h"
#include "../../../services/config/config.h"
#include "../../../services/crypto/crypto.h"
#include "../../../services/convert/convert.h"
#include "../../../lib/polyfills/memset_s.h"
#include "../../../lib/roll_value/roll_value.h"
#include "../../scene_director.h"
#include "../token_menu/totp_scene_token_menu.h"
#include "../../services/hid_worker/hid_worker.h"
#include "../../../workers/type_code/type_code.h"
#define TOKEN_LIFETIME 30
#define DIGIT_TO_CHAR(digit) ((digit) + '0')
typedef struct {
uint16_t current_token_index;
@ -24,60 +24,108 @@ typedef struct {
char* last_code_name;
bool need_token_update;
uint32_t last_token_gen_time;
TotpHidWorkerTypeContext* hid_worker_context;
TotpTypeCodeWorkerContext* type_code_worker_context;
NotificationMessage const** notification_sequence_new_token;
NotificationMessage const** notification_sequence_badusb;
} SceneState;
static const NotificationSequence notification_sequence_new_token = {
&message_display_backlight_on,
&message_green_255,
&message_vibro_on,
&message_note_c5,
&message_delay_50,
&message_vibro_off,
&message_sound_off,
NULL,
};
static const NotificationSequence notification_sequence_badusb = {
&message_vibro_on,
&message_note_d5,
&message_delay_50,
&message_note_e4,
&message_delay_50,
&message_note_f3,
&message_delay_50,
&message_vibro_off,
&message_sound_off,
NULL,
};
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 == OTP_ERROR) {
memset(&str[0], '-', str_token_length);
} else {
if(len == TOTP_8_DIGITS) {
str[7] = DIGIT_TO_CHAR(i_token_code % 10);
str[6] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10);
str[5] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10);
} else if(len == TOTP_6_DIGITS) {
str[5] = DIGIT_TO_CHAR(i_token_code % 10);
static const NotificationSequence*
get_notification_sequence_new_token(const PluginState* plugin_state, SceneState* scene_state) {
if(scene_state->notification_sequence_new_token == NULL) {
uint8_t i = 0;
uint8_t length = 4;
if(plugin_state->notification_method & NotificationMethodVibro) {
length += 2;
}
str[4] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10);
str[3] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10);
str[2] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10);
str[1] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10);
str[0] = DIGIT_TO_CHAR((i_token_code = i_token_code / 10) % 10);
if(plugin_state->notification_method & NotificationMethodSound) {
length += 2;
}
scene_state->notification_sequence_new_token = malloc(sizeof(void*) * length);
furi_check(scene_state->notification_sequence_new_token != NULL);
scene_state->notification_sequence_new_token[i++] = &message_display_backlight_on;
scene_state->notification_sequence_new_token[i++] = &message_green_255;
if(plugin_state->notification_method & NotificationMethodVibro) {
scene_state->notification_sequence_new_token[i++] = &message_vibro_on;
}
if(plugin_state->notification_method & NotificationMethodSound) {
scene_state->notification_sequence_new_token[i++] = &message_note_c5;
}
scene_state->notification_sequence_new_token[i++] = &message_delay_50;
if(plugin_state->notification_method & NotificationMethodVibro) {
scene_state->notification_sequence_new_token[i++] = &message_vibro_off;
}
if(plugin_state->notification_method & NotificationMethodSound) {
scene_state->notification_sequence_new_token[i++] = &message_sound_off;
}
scene_state->notification_sequence_new_token[i++] = NULL;
}
return (NotificationSequence*)scene_state->notification_sequence_new_token;
}
static const NotificationSequence*
get_notification_sequence_badusb(const PluginState* plugin_state, SceneState* scene_state) {
if(scene_state->notification_sequence_badusb == NULL) {
uint8_t i = 0;
uint8_t length = 3;
if(plugin_state->notification_method & NotificationMethodVibro) {
length += 2;
}
if(plugin_state->notification_method & NotificationMethodSound) {
length += 6;
}
scene_state->notification_sequence_badusb = malloc(sizeof(void*) * length);
furi_check(scene_state->notification_sequence_badusb != NULL);
scene_state->notification_sequence_badusb[i++] = &message_blue_255;
if(plugin_state->notification_method & NotificationMethodVibro) {
scene_state->notification_sequence_badusb[i++] = &message_vibro_on;
}
if(plugin_state->notification_method & NotificationMethodSound) {
scene_state->notification_sequence_badusb[i++] = &message_note_d5; //-V525
scene_state->notification_sequence_badusb[i++] = &message_delay_50;
scene_state->notification_sequence_badusb[i++] = &message_note_e4;
scene_state->notification_sequence_badusb[i++] = &message_delay_50;
scene_state->notification_sequence_badusb[i++] = &message_note_f3;
}
scene_state->notification_sequence_badusb[i++] = &message_delay_50;
if(plugin_state->notification_method & NotificationMethodVibro) {
scene_state->notification_sequence_badusb[i++] = &message_vibro_off;
}
if(plugin_state->notification_method & NotificationMethodSound) {
scene_state->notification_sequence_badusb[i++] = &message_sound_off;
}
scene_state->notification_sequence_badusb[i++] = NULL;
}
return (NotificationSequence*)scene_state->notification_sequence_badusb;
}
static void int_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount len) {
if(i_token_code == OTP_ERROR) {
memset(&str[0], '-', len);
} else {
for(int i = len - 1; i >= 0; i--) {
str[i] = CONVERT_DIGIT_TO_CHAR(i_token_code % 10);
i_token_code = i_token_code / 10;
}
}
str[len] = '\0';
}
TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
@ -137,7 +185,7 @@ void totp_scene_generate_token_activate(
AlignCenter);
}
dialog_message_show(plugin_state->dialogs, message);
dialog_message_show(plugin_state->dialogs_app, message);
dialog_message_free(message);
}
}
@ -152,9 +200,9 @@ void totp_scene_generate_token_activate(
plugin_state->current_scene_state = scene_state;
FURI_LOG_D(LOGGING_TAG, "Timezone set to: %f", (double)plugin_state->timezone_offset);
update_totp_params(plugin_state);
scene_state->hid_worker_context = totp_hid_worker_start();
scene_state->hid_worker_context->string = &scene_state->last_code[0];
scene_state->hid_worker_context->string_length = TOTP_TOKEN_DIGITS_MAX_COUNT + 1;
scene_state->type_code_worker_context = totp_type_code_worker_start();
scene_state->type_code_worker_context->string = &scene_state->last_code[0];
scene_state->type_code_worker_context->string_length = TOTP_TOKEN_DIGITS_MAX_COUNT + 1;
}
void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state) {
@ -196,15 +244,16 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
->data);
if(tokenInfo->token != NULL && tokenInfo->token_length > 0) {
furi_mutex_acquire(scene_state->hid_worker_context->string_sync, FuriWaitForever);
furi_mutex_acquire(
scene_state->type_code_worker_context->string_sync, FuriWaitForever);
size_t key_length;
uint8_t* key = totp_crypto_decrypt(
tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
i_token_to_str(
int_token_to_str(
totp_at(
get_totp_algo_impl(tokenInfo->algo),
token_info_get_digits_count(tokenInfo),
tokenInfo->digits,
key,
key_length,
curr_ts,
@ -215,14 +264,17 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
memset_s(key, key_length, 0, key_length);
free(key);
} else {
furi_mutex_acquire(scene_state->hid_worker_context->string_sync, FuriWaitForever);
i_token_to_str(0, scene_state->last_code, tokenInfo->digits);
furi_mutex_acquire(
scene_state->type_code_worker_context->string_sync, FuriWaitForever);
int_token_to_str(0, scene_state->last_code, tokenInfo->digits);
}
furi_mutex_release(scene_state->hid_worker_context->string_sync);
furi_mutex_release(scene_state->type_code_worker_context->string_sync);
if(is_new_token_time) {
notification_message(plugin_state->notification, &notification_sequence_new_token);
notification_message(
plugin_state->notification_app,
get_notification_sequence_new_token(plugin_state, scene_state));
}
}
@ -288,8 +340,11 @@ bool totp_scene_generate_token_handle_event(
SceneState* scene_state;
if(event->input.type == InputTypeLong && event->input.key == InputKeyDown) {
scene_state = (SceneState*)plugin_state->current_scene_state;
totp_hid_worker_notify(scene_state->hid_worker_context, TotpHidWorkerEvtType);
notification_message(plugin_state->notification, &notification_sequence_badusb);
totp_type_code_worker_notify(
scene_state->type_code_worker_context, TotpTypeCodeWorkerEventType);
notification_message(
plugin_state->notification_app,
get_notification_sequence_badusb(plugin_state, scene_state));
return true;
}
@ -342,7 +397,15 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) {
if(plugin_state->current_scene_state == NULL) return;
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
totp_hid_worker_stop(scene_state->hid_worker_context);
totp_type_code_worker_stop(scene_state->type_code_worker_context);
if(scene_state->notification_sequence_new_token != NULL) {
free(scene_state->notification_sequence_new_token);
}
if(scene_state->notification_sequence_badusb != NULL) {
free(scene_state->notification_sequence_badusb);
}
free(scene_state);
plugin_state->current_scene_state = NULL;

View File

@ -1,10 +1,8 @@
#pragma once
#include <gui/gui.h>
#include <furi.h>
#include <furi_hal.h>
#include "../../types/plugin_state.h"
#include "../../types/plugin_event.h"
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
typedef struct {
uint16_t current_token_index;

View File

@ -1,17 +1,17 @@
#include "totp_scene_token_menu.h"
#include <gui/gui.h>
#include <dialogs/dialogs.h>
#include "../../services/ui/ui_controls.h"
#include "../../services/ui/constants.h"
#include "../scene_director.h"
#include "../../services/config/config.h"
#include "../../services/list/list.h"
#include "../../types/token_info.h"
#include "../../ui_controls.h"
#include "../../constants.h"
#include "../../scene_director.h"
#include "../../../services/config/config.h"
#include "../../../lib/list/list.h"
#include "../../../types/token_info.h"
#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"
#include "../../../types/nullable.h"
#include "../../../lib/roll_value/roll_value.h"
#define SCREEN_HEIGHT_THIRD (SCREEN_HEIGHT / 3)
#define SCREEN_HEIGHT_THIRD_CENTER (SCREEN_HEIGHT_THIRD >> 1)
@ -143,7 +143,7 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt
AlignCenter,
AlignCenter);
DialogMessageButton dialog_result =
dialog_message_show(plugin_state->dialogs, message);
dialog_message_show(plugin_state->dialogs_app, message);
dialog_message_free(message);
if(dialog_result == DialogMessageButtonRight &&
!scene_state->current_token_index.is_null) {

View File

@ -1,10 +1,8 @@
#pragma once
#include <gui/gui.h>
#include <furi.h>
#include <furi_hal.h>
#include "../../types/plugin_state.h"
#include "../../types/plugin_event.h"
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
typedef struct {
uint16_t current_token_index;

View File

@ -1,9 +1,11 @@
#pragma once
typedef uint8_t Scene;
/**
* @brief TOTP application scenes
*/
typedef enum {
enum Scenes {
/**
* @brief Empty scene which does nothing
*/
@ -33,4 +35,4 @@ typedef enum {
* @brief Scene where user can change application settings
*/
TotpSceneAppSettings
} Scene;
};

View File

@ -1,4 +1,5 @@
#include "hid_worker.h"
#include "type_code.h"
#include "../../services/convert/convert.h"
static const uint8_t hid_number_keys[10] = {
HID_KEYBOARD_0,
@ -12,18 +13,18 @@ static const uint8_t hid_number_keys[10] = {
HID_KEYBOARD_8,
HID_KEYBOARD_9};
static void totp_hid_worker_restore_usb_mode(TotpHidWorkerTypeContext* context) {
static void totp_type_code_worker_restore_usb_mode(TotpTypeCodeWorkerContext* context) {
if(context->usb_mode_prev != NULL) {
furi_hal_usb_set_config(context->usb_mode_prev, NULL);
context->usb_mode_prev = NULL;
}
}
static inline bool totp_hid_worker_stop_requested() {
return furi_thread_flags_get() & TotpHidWorkerEvtStop;
static inline bool totp_type_code_worker_stop_requested() {
return furi_thread_flags_get() & TotpTypeCodeWorkerEventStop;
}
static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
static void totp_type_code_worker_type_code(TotpTypeCodeWorkerContext* context) {
context->usb_mode_prev = furi_hal_usb_get_config();
furi_hal_usb_unlock();
furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true);
@ -31,14 +32,14 @@ static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
do {
furi_delay_ms(500);
i++;
} while(!furi_hal_hid_is_connected() && i < 100 && !totp_hid_worker_stop_requested());
} while(!furi_hal_hid_is_connected() && i < 100 && !totp_type_code_worker_stop_requested());
if(furi_hal_hid_is_connected() &&
furi_mutex_acquire(context->string_sync, 500) == FuriStatusOk) {
furi_delay_ms(500);
i = 0;
while(i < context->string_length && context->string[i] != 0) {
uint8_t digit = context->string[i] - '0';
uint8_t digit = CONVERT_CHAR_TO_DIGIT(context->string[i]);
if(digit > 9) break;
uint8_t hid_kb_key = hid_number_keys[digit];
furi_hal_hid_kb_press(hid_kb_key);
@ -52,24 +53,26 @@ static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
furi_delay_ms(100);
}
totp_hid_worker_restore_usb_mode(context);
totp_type_code_worker_restore_usb_mode(context);
}
static int32_t totp_hid_worker_callback(void* context) {
static int32_t totp_type_code_worker_callback(void* context) {
ValueMutex context_mutex;
if(!init_mutex(&context_mutex, context, sizeof(TotpHidWorkerTypeContext))) {
if(!init_mutex(&context_mutex, context, sizeof(TotpTypeCodeWorkerContext))) {
return 251;
}
while(true) {
uint32_t flags = furi_thread_flags_wait(
TotpHidWorkerEvtStop | TotpHidWorkerEvtType, FuriFlagWaitAny, FuriWaitForever);
TotpTypeCodeWorkerEventStop | TotpTypeCodeWorkerEventType,
FuriFlagWaitAny,
FuriWaitForever);
furi_check((flags & FuriFlagError) == 0); //-V562
if(flags & TotpHidWorkerEvtStop) break;
if(flags & TotpTypeCodeWorkerEventStop) break;
TotpHidWorkerTypeContext* h_context = acquire_mutex_block(&context_mutex);
if(flags & TotpHidWorkerEvtType) {
totp_hid_worker_type_code(h_context);
TotpTypeCodeWorkerContext* h_context = acquire_mutex_block(&context_mutex);
if(flags & TotpTypeCodeWorkerEventType) {
totp_type_code_worker_type_code(h_context);
}
release_mutex(&context_mutex, h_context);
@ -80,8 +83,8 @@ static int32_t totp_hid_worker_callback(void* context) {
return 0;
}
TotpHidWorkerTypeContext* totp_hid_worker_start() {
TotpHidWorkerTypeContext* context = malloc(sizeof(TotpHidWorkerTypeContext));
TotpTypeCodeWorkerContext* totp_type_code_worker_start() {
TotpTypeCodeWorkerContext* context = malloc(sizeof(TotpTypeCodeWorkerContext));
furi_check(context != NULL);
context->string_sync = furi_mutex_alloc(FuriMutexTypeNormal);
context->thread = furi_thread_alloc();
@ -89,22 +92,24 @@ TotpHidWorkerTypeContext* totp_hid_worker_start() {
furi_thread_set_name(context->thread, "TOTPHidWorker");
furi_thread_set_stack_size(context->thread, 1024);
furi_thread_set_context(context->thread, context);
furi_thread_set_callback(context->thread, totp_hid_worker_callback);
furi_thread_set_callback(context->thread, totp_type_code_worker_callback);
furi_thread_start(context->thread);
return context;
}
void totp_hid_worker_stop(TotpHidWorkerTypeContext* context) {
void totp_type_code_worker_stop(TotpTypeCodeWorkerContext* context) {
furi_assert(context != NULL);
furi_thread_flags_set(furi_thread_get_id(context->thread), TotpHidWorkerEvtStop);
furi_thread_flags_set(furi_thread_get_id(context->thread), TotpTypeCodeWorkerEventStop);
furi_thread_join(context->thread);
furi_thread_free(context->thread);
furi_mutex_free(context->string_sync);
totp_hid_worker_restore_usb_mode(context);
totp_type_code_worker_restore_usb_mode(context);
free(context);
}
void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event) {
void totp_type_code_worker_notify(
TotpTypeCodeWorkerContext* context,
TotpTypeCodeWorkerEvent event) {
furi_assert(context != NULL);
furi_thread_flags_set(furi_thread_get_id(context->thread), event);
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <stdlib.h>
#include <furi/furi.h>
#include <furi_hal.h>
typedef uint8_t TotpTypeCodeWorkerEvent;
typedef struct {
char* string;
uint8_t string_length;
FuriThread* thread;
FuriMutex* string_sync;
FuriHalUsbInterface* usb_mode_prev;
} TotpTypeCodeWorkerContext;
enum TotpTypeCodeWorkerEvents {
TotpTypeCodeWorkerEventReserved = (1 << 0),
TotpTypeCodeWorkerEventStop = (1 << 1),
TotpTypeCodeWorkerEventType = (1 << 2)
};
TotpTypeCodeWorkerContext* totp_type_code_worker_start();
void totp_type_code_worker_stop(TotpTypeCodeWorkerContext* context);
void totp_type_code_worker_notify(
TotpTypeCodeWorkerContext* context,
TotpTypeCodeWorkerEvent event);