Update totp

This commit is contained in:
Willy-JL
2023-08-13 03:02:22 +02:00
parent 1d3228768f
commit 7504e58244
81 changed files with 655 additions and 1518 deletions

3
.gitmodules vendored
View File

@@ -41,3 +41,6 @@
[submodule "lib/stm32wb_copro"]
path = lib/stm32wb_copro
url = https://github.com/flipperdevices/stm32wb_copro.git
[submodule "applications/external/totp/lib/wolfssl"]
path = applications/external/totp/lib/wolfssl
url = https://github.com/wolfSSL/wolfssl.git

View File

@@ -4,10 +4,18 @@ App(
apptype=FlipperAppType.EXTERNAL,
entry_point="totp_app",
cdefines=["APP_TOTP"],
requires=["gui", "cli", "dialogs", "storage", "input", "notification", "bt"],
requires=[
"gui",
"cli",
"dialogs",
"storage",
"input",
"notification",
"bt"
],
stack_size=2 * 1024,
order=20,
fap_version="3.20",
fap_version="4.01",
fap_author="Alexander Kopachov (@akopachov)",
fap_description="Software-based TOTP authenticator for Flipper Zero device",
fap_weburl="https://github.com/akopachov/flipper-zero_authenticator",
@@ -33,5 +41,19 @@ App(
Lib(
name="fonts",
),
Lib(
name="wolfssl",
sources=[
"wolfcrypt/src/pwdbased.c",
"wolfcrypt/src/hmac.c",
"wolfcrypt/src/hash.c",
"wolfcrypt/src/sha.c",
"wolfcrypt/src/sha256.c",
"wolfcrypt/src/sha512.c"
],
cflags=["-Wno-error"],
cdefines=["HAVE_CONFIG_H"],
cincludes=["config/wolfssl"]
),
],
)

View File

@@ -79,6 +79,7 @@ static TotpIteratorUpdateTokenResult
return TotpIteratorUpdateTokenResultSuccess;
}
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_add_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ADD ", " TOTP_CLI_COMMAND_ADD_ALT
", " TOTP_CLI_COMMAND_ADD_ALT2 " Add new token\r\n");
@@ -155,6 +156,7 @@ void totp_cli_command_add_docopt_options() {
TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME
" - Type slower\r\n");
}
#endif
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {

View File

@@ -1,6 +1,7 @@
#pragma once
#include <cli/cli.h>
#include "../../../config/app/config.h"
#include "../../../types/plugin_state.h"
#define TOTP_CLI_COMMAND_ADD "add"
@@ -8,7 +9,9 @@
#define TOTP_CLI_COMMAND_ADD_ALT2 "new"
void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_add_docopt_commands();
void totp_cli_command_add_docopt_usage();
void totp_cli_command_add_docopt_arguments();
void totp_cli_command_add_docopt_options();
void totp_cli_command_add_docopt_options();
#endif

View File

@@ -15,6 +15,7 @@
#define TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT_PREFIX "-k"
#define TOTP_CLI_COMMAND_AUTOMATION_ARG_KB_LAYOUT "layout"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_automation_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_AUTOMATION " Get or set automation settings\r\n");
}
@@ -45,6 +46,7 @@ void totp_cli_command_automation_docopt_options() {
", " TOTP_CLI_COMMAND_AUTOMATION_LAYOUT_AZERTY
"\r\n");
}
#endif
static void print_method(AutomationMethod method, const char* color) {
#ifdef TOTP_BADBT_AUTOMATION_ENABLED

View File

@@ -2,11 +2,14 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_AUTOMATION "automation"
void totp_cli_command_automation_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_automation_docopt_commands();
void totp_cli_command_automation_docopt_usage();
void totp_cli_command_automation_docopt_arguments();
void totp_cli_command_automation_docopt_options();
void totp_cli_command_automation_docopt_options();
#endif

View File

@@ -10,6 +10,7 @@
#define TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX "-f"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_delete_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DELETE ", " TOTP_CLI_COMMAND_DELETE_ALT
" Delete existing token\r\n");
@@ -30,6 +31,7 @@ void totp_cli_command_delete_docopt_options() {
TOTP_CLI_PRINTF(" " DOCOPT_SWITCH(
TOTP_CLI_COMMAND_DELETE_ARG_FORCE_PREFIX) " Force command to do not ask user for interactive confirmation\r\n");
}
#endif
void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {

View File

@@ -2,12 +2,15 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_DELETE "delete"
#define TOTP_CLI_COMMAND_DELETE_ALT "rm"
void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_delete_docopt_commands();
void totp_cli_command_delete_docopt_usage();
void totp_cli_command_delete_docopt_arguments();
void totp_cli_command_delete_docopt_options();
void totp_cli_command_delete_docopt_options();
#endif

View File

@@ -37,6 +37,7 @@ static void print_automation_features(const TokenInfo* token_info) {
}
}
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_details_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DETAILS ", " TOTP_CLI_COMMAND_DETAILS_ALT
" Displays token details\r\n");
@@ -47,6 +48,7 @@ void totp_cli_command_details_docopt_usage() {
TOTP_CLI_COMMAND_DETAILS
" | " TOTP_CLI_COMMAND_DETAILS_ALT) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ARG_INDEX) "\r\n");
}
#endif
void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {

View File

@@ -2,10 +2,13 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_DETAILS "lsattr"
#define TOTP_CLI_COMMAND_DETAILS_ALT "cat"
void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_details_docopt_commands();
void totp_cli_command_details_docopt_usage();
#endif

View File

@@ -12,6 +12,7 @@
#include "../automation/automation.h"
#include "../details/details.h"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_help_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT
", " TOTP_CLI_COMMAND_HELP_ALT2 " Show command usage help\r\n");
@@ -22,8 +23,10 @@ void totp_cli_command_help_docopt_usage() {
TOTP_CLI_COMMAND_HELP " | " TOTP_CLI_COMMAND_HELP_ALT
" | " TOTP_CLI_COMMAND_HELP_ALT2) "\r\n");
}
#endif
void totp_cli_command_help_handle() {
#ifdef TOTP_CLI_RICH_HELP_ENABLED
TOTP_CLI_PRINTF("Usage:\r\n");
totp_cli_command_help_docopt_usage();
totp_cli_command_list_docopt_usage();
@@ -66,4 +69,8 @@ void totp_cli_command_help_handle() {
totp_cli_command_delete_docopt_options();
totp_cli_command_pin_docopt_options();
totp_cli_command_automation_docopt_options();
#else
TOTP_CLI_PRINTF(
"All the TOTP CLI commands, their arguments, options and usage can be found here https://t.ly/_6pJG");
#endif
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "../../../config/app/config.h"
#include <cli/cli.h>
#define TOTP_CLI_COMMAND_HELP "help"
@@ -7,5 +8,7 @@
#define TOTP_CLI_COMMAND_HELP_ALT2 "?"
void totp_cli_command_help_handle();
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_help_docopt_commands();
void totp_cli_command_help_docopt_usage();
void totp_cli_command_help_docopt_usage();
#endif

View File

@@ -6,6 +6,7 @@
#include "../../../ui/scene_director.h"
#include "../../cli_helpers.h"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
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");
@@ -15,6 +16,7 @@ void totp_cli_command_list_docopt_usage() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " DOCOPT_REQUIRED(
TOTP_CLI_COMMAND_LIST " | " TOTP_CLI_COMMAND_LIST_ALT) "\r\n");
}
#endif
void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) {
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {

View File

@@ -2,10 +2,13 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_LIST "list"
#define TOTP_CLI_COMMAND_LIST_ALT "ls"
void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_list_docopt_commands();
void totp_cli_command_list_docopt_usage();
#endif

View File

@@ -10,6 +10,7 @@
#define TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX "new_index"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_move_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_MOVE ", " TOTP_CLI_COMMAND_MOVE_ALT
" Move token\r\n");
@@ -26,6 +27,7 @@ void totp_cli_command_move_docopt_arguments() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX
" New token index in the list\r\n");
}
#endif
void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {

View File

@@ -2,11 +2,14 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_MOVE "move"
#define TOTP_CLI_COMMAND_MOVE_ALT "mv"
void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_move_docopt_commands();
void totp_cli_command_move_docopt_usage();
void totp_cli_command_move_docopt_arguments();
void totp_cli_command_move_docopt_arguments();
#endif

View File

@@ -9,6 +9,7 @@
#define TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND "sound"
#define TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO "vibro"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_notification_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NOTIFICATION
" Get or set notification method\r\n");
@@ -27,6 +28,7 @@ void totp_cli_command_notification_docopt_arguments() {
", " TOTP_CLI_COMMAND_NOTIFICATION_METHOD_SOUND
", " TOTP_CLI_COMMAND_NOTIFICATION_METHOD_VIBRO "\r\n");
}
#endif
static void
totp_cli_command_notification_print_method(NotificationMethod method, const char* color) {

View File

@@ -2,10 +2,13 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_NOTIFICATION "notify"
void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_notification_docopt_commands();
void totp_cli_command_notification_docopt_usage();
void totp_cli_command_notification_docopt_arguments();
void totp_cli_command_notification_docopt_arguments();
#endif

View File

@@ -15,6 +15,7 @@
#define TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT_PREFIX "-c"
#define TOTP_CLI_COMMAND_PIN_ARG_NEW_CRYPTO_KEY_SLOT "slot"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_pin_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_PIN " Set\\change\\remove PIN\r\n");
}
@@ -37,6 +38,7 @@ void totp_cli_command_pin_docopt_options() {
ACCEPTABLE_CRYPTO_KEY_SLOT_START,
ACCEPTABLE_CRYPTO_KEY_SLOT_END);
}
#endif
static inline uint8_t totp_cli_key_to_pin_code(uint8_t key) {
uint8_t code = 0;

View File

@@ -2,10 +2,13 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_PIN "pin"
void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_pin_docopt_commands();
void totp_cli_command_pin_docopt_usage();
void totp_cli_command_pin_docopt_options();
void totp_cli_command_pin_docopt_options();
#endif

View File

@@ -8,6 +8,7 @@
#define TOTP_CLI_RESET_CONFIRMATION_KEYWORD "YES"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_reset_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_RESET
" Reset application to default settings\r\n");
@@ -16,6 +17,7 @@ void totp_cli_command_reset_docopt_commands() {
void totp_cli_command_reset_docopt_usage() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_RESET "\r\n");
}
#endif
void totp_cli_command_reset_handle(PluginState* plugin_state, Cli* cli) {
TOTP_CLI_LOCK_UI(plugin_state);

View File

@@ -2,9 +2,12 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_RESET "reset"
void totp_cli_command_reset_handle(PluginState* plugin_state, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_reset_docopt_commands();
void totp_cli_command_reset_docopt_usage();
void totp_cli_command_reset_docopt_usage();
#endif

View File

@@ -6,6 +6,7 @@
#define TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE "timezone"
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_timezone_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE ", " TOTP_CLI_COMMAND_TIMEZONE_ALT
" Get or set current timezone\r\n");
@@ -22,6 +23,7 @@ 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");
}
#endif
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {

View File

@@ -2,11 +2,14 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_TIMEZONE "timezone"
#define TOTP_CLI_COMMAND_TIMEZONE_ALT "tz"
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_timezone_docopt_commands();
void totp_cli_command_timezone_docopt_usage();
void totp_cli_command_timezone_docopt_arguments();
void totp_cli_command_timezone_docopt_arguments();
#endif

View File

@@ -107,6 +107,7 @@ static TotpIteratorUpdateTokenResult
return TotpIteratorUpdateTokenResultSuccess;
}
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_update_docopt_commands() {
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_UPDATE " Update existing token\r\n");
}
@@ -129,6 +130,7 @@ void totp_cli_command_update_docopt_options() {
TOTP_CLI_PRINTF(" " DOCOPT_SWITCH(
TOTP_CLI_COMMAND_UPDATE_ARG_SECRET_PREFIX) " Update token secret\r\n");
}
#endif
void totp_cli_command_update_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {

View File

@@ -2,10 +2,13 @@
#include <cli/cli.h>
#include "../../../types/plugin_state.h"
#include "../../../config/app/config.h"
#define TOTP_CLI_COMMAND_UPDATE "update"
void totp_cli_command_update_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
#ifdef TOTP_CLI_RICH_HELP_ENABLED
void totp_cli_command_update_docopt_commands();
void totp_cli_command_update_docopt_usage();
void totp_cli_command_update_docopt_options();
void totp_cli_command_update_docopt_options();
#endif

View File

@@ -0,0 +1,42 @@
// Application automatic lock timeout if user IDLE. (ticks)
#ifndef TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC
#define TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC (60)
#endif
// Enables\disables Bluetooth token input automation
#ifndef TOTP_NO_BADBT_AUTOMATION
#define TOTP_BADBT_AUTOMATION_ENABLED
#endif
// Enables\disables backward compatibility with crypto algorithms v1
#ifndef TOTP_NO_OBSOLETE_CRYPTO_V1_COMPATIBILITY
#define TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
#endif
// Enables\disables backward compatibility with crypto algorithms v2
#ifndef TOTP_NO_OBSOLETE_CRYPTO_V2_COMPATIBILITY
#define TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
#endif
// Enables\disables userfriendly TOTP CLI help text
// If disabled, it will print a link to a wiki page
#ifndef TOTP_CLI_NO_RICH_HELP
#define TOTP_CLI_RICH_HELP_ENABLED
#endif
// Enables\disables "Add new token" UI
// If disabled it will print a link to wiki page
#ifndef TOTP_UI_NO_ADD_NEW_TOKEN
#define TOTP_UI_ADD_NEW_TOKEN_ENABLED
#endif
// List of compatible firmwares
#define TOTP_FIRMWARE_OFFICIAL_STABLE (1)
#define TOTP_FIRMWARE_OFFICIAL_DEV (2)
#define TOTP_FIRMWARE_XTREME_UL (3)
// End of list
// Target firmware
#ifndef TOTP_TARGET_FIRMWARE
#define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_XTREME_UL
#endif

View File

@@ -0,0 +1,34 @@
#pragma once
#define NO_OLD_SHA_NAMES
#define WOLFCRYPT_ONLY
#define NO_SIG_WRAPPER
#define NO_AES
#define NO_AES_CBC
#define NO_DES3
#define NO_DSA
#define NO_RSA
#define NO_DH
#define NO_RC4
#define NO_MD4
#define NO_MD5
#define NO_PKCS12
#define NO_PKCS8
#define WC_NO_RNG
#define NO_FILESYSTEM
#define NO_WRITEV
#define NO_MAIN_DRIVER
#define NO_DEV_RANDOM
#define WOLFSSL_SHA512
#define WOLFSSL_NOSHA512_224
#define WOLFSSL_NOSHA512_256
#define USE_SLOW_SHA512
#define USE_SLOW_SHA256
#define USE_SLOW_SHA
#define NO_CERTS
#define NO_WOLFSSL_MEMORY
#define WOLFSSL_NO_PEM
#define NO_PSK
#define NO_ERROR_STRINGS
#define NO_OLD_TLS
#define SINGLE_THREADED

View File

@@ -1,20 +0,0 @@
// Application automatic lock timeout if user IDLE. (ticks)
#ifndef TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC
#define TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC (60)
#endif
// Include Bluetooth token input automation
#ifndef TOTP_NO_BADBT_AUTOMATION
#define TOTP_BADBT_AUTOMATION_ENABLED
#endif
// List of compatible firmwares
#define TOTP_FIRMWARE_OFFICIAL_STABLE (1)
#define TOTP_FIRMWARE_OFFICIAL_DEV (2)
#define TOTP_FIRMWARE_XTREME_UL (3)
// End of list
// Target firmware
#ifndef TOTP_TARGET_FIRMWARE
#define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_XTREME_UL
#endif

View File

@@ -25,4 +25,4 @@ TOTP_ROLL_VALUE_FN(int8_t, int8_t)
TOTP_ROLL_VALUE_FN(uint8_t, int8_t)
TOTP_ROLL_VALUE_FN(size_t, int16_t)
TOTP_ROLL_VALUE_FN(size_t, int16_t);

View File

@@ -8,7 +8,7 @@
#include <memset_s.h>
#include "../../types/common.h"
#include "../../types/token_info.h"
#include "../../features_config.h"
#include "../../config/app/config.h"
#include "../crypto/crypto_facade.h"
#include "../crypto/constants.h"
#include "migrations/common_migration.h"
@@ -112,7 +112,8 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) {
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
bool conf_file_exists = storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK;
if(!conf_file_exists) {
if(!conf_file_exists &&
storage_common_stat(storage, EXT_PATH("authenticator"), NULL) == FSE_OK) {
FURI_LOG_I(LOGGING_TAG, "Application catalog needs to be migrated");
FS_Error migration_result =
storage_common_migrate(storage, EXT_PATH("authenticator"), CONFIG_FILE_DIRECTORY_PATH);
@@ -148,7 +149,7 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) {
flipper_format_write_comment_cstr(
fff_data_file,
"Config file format specification can be found here: https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md");
"Config file format specification can be found here: https://t.ly/zwQjE");
float tmp_tz = 0;
flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &tmp_tz, 1);
@@ -396,10 +397,10 @@ bool totp_config_file_load(PluginState* const plugin_state) {
if(!flipper_format_read_hex(
fff_data_file,
TOTP_CONFIG_KEY_BASE_IV,
&plugin_state->crypto_settings.base_iv[0],
CRYPTO_IV_LENGTH)) {
FURI_LOG_D(LOGGING_TAG, "Missing base IV");
TOTP_CONFIG_KEY_SALT,
&plugin_state->crypto_settings.salt[0],
CRYPTO_SALT_LENGTH)) {
FURI_LOG_D(LOGGING_TAG, "Missing salt");
}
if(!flipper_format_rewind(fff_data_file)) {
@@ -529,9 +530,9 @@ bool totp_config_file_update_crypto_signatures(const PluginState* plugin_state)
if(!flipper_format_insert_or_update_hex(
config_file,
TOTP_CONFIG_KEY_BASE_IV,
plugin_state->crypto_settings.base_iv,
CRYPTO_IV_LENGTH)) {
TOTP_CONFIG_KEY_SALT,
&plugin_state->crypto_settings.salt[0],
CRYPTO_SALT_LENGTH)) {
break;
}
@@ -592,7 +593,7 @@ bool totp_config_file_update_encryption(
CryptoSettings old_crypto_settings = plugin_state->crypto_settings;
memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH);
memset(&plugin_state->crypto_settings.base_iv[0], 0, CRYPTO_IV_LENGTH);
memset(&plugin_state->crypto_settings.salt[0], 0, CRYPTO_SALT_LENGTH);
if(plugin_state->crypto_settings.crypto_verify_data != NULL) {
free(plugin_state->crypto_settings.crypto_verify_data);
plugin_state->crypto_settings.crypto_verify_data = NULL;
@@ -724,4 +725,4 @@ bool totp_config_file_ensure_latest_encryption(
TokenInfoIteratorContext* totp_config_get_token_iterator_context(const PluginState* plugin_state) {
return plugin_state->config_file_context->token_info_iterator_context;
}
}

View File

@@ -2,9 +2,9 @@
#include <storage/storage.h>
#define CONFIG_FILE_DIRECTORY_PATH STORAGE_APP_DATA_PATH_PREFIX
#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("apps_data/totp")
#define CONFIG_FILE_HEADER "Flipper TOTP plugin config file"
#define CONFIG_FILE_ACTUAL_VERSION (8)
#define CONFIG_FILE_ACTUAL_VERSION (9)
#define TOTP_CONFIG_KEY_TIMEZONE "Timezone"
#define TOTP_CONFIG_KEY_TOKEN_NAME "TokenName"
@@ -14,7 +14,7 @@
#define TOTP_CONFIG_KEY_TOKEN_DURATION "TokenDuration"
#define TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES "TokenAutomationFeatures"
#define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto"
#define TOTP_CONFIG_KEY_BASE_IV "BaseIV"
#define TOTP_CONFIG_KEY_SALT "Salt"
#define TOTP_CONFIG_KEY_PINSET "PinIsSet"
#define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod"
#define TOTP_CONFIG_KEY_AUTOMATION_METHOD "AutomationMethod"

View File

@@ -4,6 +4,8 @@
#include "../../../types/automation_kb_layout.h"
#include <flipper_format/flipper_format_i.h>
#define TOTP_OLD_CONFIG_KEY_BASE_IV "BaseIV"
bool totp_config_migrate_to_latest(
FlipperFormat* fff_data_file,
FlipperFormat* fff_backup_data_file) {
@@ -40,8 +42,13 @@ bool totp_config_migrate_to_latest(
flipper_format_rewind(fff_backup_data_file);
if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str);
if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_SALT, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_SALT, temp_str);
} else if(
flipper_format_rewind(fff_backup_data_file) &&
flipper_format_read_string(
fff_backup_data_file, TOTP_OLD_CONFIG_KEY_BASE_IV, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_SALT, temp_str);
}
flipper_format_rewind(fff_backup_data_file);

View File

@@ -7,7 +7,7 @@
#include "../../types/crypto_settings.h"
#define CONFIG_FILE_PART_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf.part"
#define STREAM_COPY_BUFFER_SIZE 128
#define STREAM_COPY_BUFFER_SIZE (128)
struct TokenInfoIteratorContext {
size_t total_count;
@@ -547,4 +547,6 @@ void totp_token_info_iterator_attach_to_config_file(
TokenInfoIteratorContext* context,
FlipperFormat* config_file) {
context->config_file = config_file;
Stream* stream = flipper_format_get_raw_stream(context->config_file);
stream_seek(stream, context->last_seek_offset, StreamOffsetFromStart);
}

View File

@@ -1,11 +1,14 @@
#pragma once
#include "polyfills.h"
#define CRYPTO_IV_LENGTH (16)
#define CRYPTO_SALT_LENGTH (16)
// According to this explanation: https://github.com/flipperdevices/flipperzero-firmware/issues/2885#issuecomment-1646664666
// disabling usage of any key which is "the same across all devices"
#define ACCEPTABLE_CRYPTO_KEY_SLOT_START (12)
#define ACCEPTABLE_CRYPTO_KEY_SLOT_END (100)
#define ACCEPTABLE_CRYPTO_KEY_SLOT_START FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_START
#define ACCEPTABLE_CRYPTO_KEY_SLOT_END FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_END
#define DEFAULT_CRYPTO_KEY_SLOT ACCEPTABLE_CRYPTO_KEY_SLOT_START
#define CRYPTO_LATEST_VERSION (2)
#define CRYPTO_LATEST_VERSION (3)

View File

@@ -1,8 +1,14 @@
#include "crypto_facade.h"
#include "../../config/app/config.h"
#include <furi_hal_crypto.h>
#include <furi/core/check.h>
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
#include "crypto_v1.h"
#endif
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
#include "crypto_v2.h"
#endif
#include "crypto_v3.h"
#include "constants.h"
bool totp_crypto_check_key_slot(uint8_t key_slot) {
@@ -11,9 +17,9 @@ bool totp_crypto_check_key_slot(uint8_t key_slot) {
return false;
}
return furi_hal_crypto_verify_key(key_slot) &&
furi_hal_crypto_store_load_key(key_slot, empty_iv) &&
furi_hal_crypto_store_unload_key(key_slot);
return furi_hal_crypto_enclave_ensure_key(key_slot) &&
furi_hal_crypto_enclave_load_key(key_slot, empty_iv) &&
furi_hal_crypto_enclave_unload_key(key_slot);
}
uint8_t* totp_crypto_encrypt(
@@ -21,15 +27,24 @@ uint8_t* totp_crypto_encrypt(
const size_t plain_data_length,
const CryptoSettings* crypto_settings,
size_t* encrypted_data_length) {
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
if(crypto_settings->crypto_version == 1) {
return totp_crypto_encrypt_v1(
plain_data, plain_data_length, crypto_settings, encrypted_data_length);
}
#endif
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
if(crypto_settings->crypto_version == 2) {
return totp_crypto_encrypt_v2(
plain_data, plain_data_length, crypto_settings, encrypted_data_length);
}
#endif
if(crypto_settings->crypto_version == 3) {
return totp_crypto_encrypt_v3(
plain_data, plain_data_length, crypto_settings, encrypted_data_length);
}
furi_crash("Unsupported crypto version");
}
@@ -39,40 +54,65 @@ uint8_t* totp_crypto_decrypt(
const size_t encrypted_data_length,
const CryptoSettings* crypto_settings,
size_t* decrypted_data_length) {
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
if(crypto_settings->crypto_version == 1) {
return totp_crypto_decrypt_v1(
encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length);
}
#endif
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
if(crypto_settings->crypto_version == 2) {
return totp_crypto_decrypt_v2(
encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length);
}
#endif
if(crypto_settings->crypto_version == 3) {
return totp_crypto_decrypt_v3(
encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length);
}
furi_crash("Unsupported crypto version");
}
CryptoSeedIVResult
totp_crypto_seed_iv(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length) {
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
if(crypto_settings->crypto_version == 1) {
return totp_crypto_seed_iv_v1(crypto_settings, pin, pin_length);
}
#endif
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
if(crypto_settings->crypto_version == 2) {
return totp_crypto_seed_iv_v2(crypto_settings, pin, pin_length);
}
#endif
if(crypto_settings->crypto_version == 3) {
return totp_crypto_seed_iv_v3(crypto_settings, pin, pin_length);
}
furi_crash("Unsupported crypto version");
}
bool totp_crypto_verify_key(const CryptoSettings* crypto_settings) {
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
if(crypto_settings->crypto_version == 1) {
return totp_crypto_verify_key_v1(crypto_settings);
}
#endif
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
if(crypto_settings->crypto_version == 2) {
return totp_crypto_verify_key_v2(crypto_settings);
}
#endif
if(crypto_settings->crypto_version == 3) {
return totp_crypto_verify_key_v3(crypto_settings);
}
furi_crash("Unsupported crypto version");
}

View File

@@ -1,4 +1,5 @@
#include "crypto_v1.h"
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
#include <stdlib.h>
#include <furi.h>
#include <furi_hal_crypto.h>
@@ -6,6 +7,7 @@
#include <furi_hal_version.h>
#include "../../types/common.h"
#include "memset_s.h"
#include "polyfills.h"
#define CRYPTO_KEY_SLOT (2)
#define CRYPTO_VERIFY_KEY_LENGTH (16)
@@ -32,9 +34,9 @@ uint8_t* totp_crypto_encrypt_v1(
furi_check(encrypted_data != NULL);
*encrypted_data_length = plain_data_aligned_length;
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
furi_hal_crypto_enclave_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length);
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
furi_hal_crypto_enclave_unload_key(CRYPTO_KEY_SLOT);
memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length);
free(plain_data_aligned);
@@ -43,9 +45,9 @@ uint8_t* totp_crypto_encrypt_v1(
furi_check(encrypted_data != NULL);
*encrypted_data_length = plain_data_length;
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
furi_hal_crypto_enclave_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length);
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
furi_hal_crypto_enclave_unload_key(CRYPTO_KEY_SLOT);
}
return encrypted_data;
@@ -59,9 +61,9 @@ uint8_t* totp_crypto_decrypt_v1(
*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, crypto_settings->iv);
furi_hal_crypto_enclave_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length);
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
furi_hal_crypto_enclave_unload_key(CRYPTO_KEY_SLOT);
return decrypted_data;
}
@@ -72,10 +74,10 @@ CryptoSeedIVResult totp_crypto_seed_iv_v1(
CryptoSeedIVResult result;
if(crypto_settings->crypto_verify_data == NULL) {
FURI_LOG_I(LOGGING_TAG, "Generating new IV");
furi_hal_random_fill_buf(&crypto_settings->base_iv[0], TOTP_IV_SIZE);
furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_LENGTH);
}
memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], TOTP_IV_SIZE);
memcpy(&crypto_settings->iv[0], &crypto_settings->salt[0], TOTP_IV_SIZE);
if(pin != NULL && pin_length > 0) {
uint8_t max_i;
if(pin_length > TOTP_IV_SIZE) {
@@ -139,4 +141,5 @@ bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings) {
free(decrypted_key);
return key_valid;
}
}
#endif

View File

@@ -1,5 +1,7 @@
#pragma once
#include "../../config/app/config.h"
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
@@ -49,4 +51,5 @@ CryptoSeedIVResult
* @param crypto_settings crypto settings
* @return \c true if cryptographic information is valid; \c false otherwise
*/
bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings);
bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings);
#endif

View File

@@ -1,13 +1,16 @@
#include "crypto_v2.h"
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
#include <stdlib.h>
#include <furi.h>
#include <furi_hal_crypto.h>
#include <furi_hal_random.h>
#include <furi_hal_version.h>
#include "../../types/common.h"
#include "../hmac/hmac_sha512.h"
#include "../../config/wolfssl/config.h"
#include <wolfssl/wolfcrypt/hmac.h>
#include "memset_s.h"
#include "constants.h"
#include "polyfills.h"
#define CRYPTO_ALIGNMENT_FACTOR (16)
@@ -46,14 +49,14 @@ uint8_t* totp_crypto_encrypt_v2(
*encrypted_data_length = plain_data_aligned_length;
furi_check(
furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
"Encryption failed: store_load_key");
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
"Encryption failed: enclave_load_key");
furi_check(
furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length),
"Encryption failed: encrypt");
furi_check(
furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot),
"Encryption failed: store_unload_key");
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
"Encryption failed: enclave_unload_key");
memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length);
free(plain_data_aligned);
@@ -63,13 +66,13 @@ uint8_t* totp_crypto_encrypt_v2(
*encrypted_data_length = plain_data_length;
furi_check(
furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
"Encryption failed: store_load_key");
furi_check(
furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length),
"Encryption failed: encrypt");
furi_check(
furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot),
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
"Encryption failed: store_unload_key");
}
@@ -85,14 +88,14 @@ uint8_t* totp_crypto_decrypt_v2(
uint8_t* decrypted_data = malloc(*decrypted_data_length);
furi_check(decrypted_data != NULL);
furi_check(
furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
"Decryption failed: store_load_key");
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
"Decryption failed: enclave_load_key");
furi_check(
furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length),
"Decryption failed: decrypt");
furi_check(
furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot),
"Decryption failed: store_unload_key");
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
"Decryption failed: enclave_unload_key");
return decrypted_data;
}
@@ -102,12 +105,10 @@ CryptoSeedIVResult totp_crypto_seed_iv_v2(
uint8_t pin_length) {
CryptoSeedIVResult result;
if(crypto_settings->crypto_verify_data == NULL) {
FURI_LOG_I(LOGGING_TAG, "Generating new IV");
furi_hal_random_fill_buf(&crypto_settings->base_iv[0], CRYPTO_IV_LENGTH);
FURI_LOG_I(LOGGING_TAG, "Generating new salt");
furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_LENGTH);
}
memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH);
const uint8_t* device_uid = get_device_uid();
uint8_t device_uid_length = get_device_uid_length();
@@ -125,16 +126,20 @@ CryptoSeedIVResult totp_crypto_seed_iv_v2(
memcpy(hmac_key + device_uid_length, pin, pin_length);
}
uint8_t hmac[HMAC_SHA512_RESULT_SIZE] = {0};
int hmac_result_code = hmac_sha512(
hmac_key, hmac_key_length, &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH, &hmac[0]);
uint8_t hmac[WC_SHA512_DIGEST_SIZE] = {0};
Hmac hmac_context;
wc_HmacSetKey(&hmac_context, WC_SHA512, hmac_key, hmac_key_length);
wc_HmacUpdate(&hmac_context, &crypto_settings->salt[0], CRYPTO_SALT_LENGTH);
int hmac_result_code = wc_HmacFinal(&hmac_context, &hmac[0]);
wc_HmacFree(&hmac_context);
memset_s(hmac_key, hmac_key_length, 0, hmac_key_length);
free(hmac_key);
if(hmac_result_code == 0) {
uint8_t offset =
hmac[HMAC_SHA512_RESULT_SIZE - 1] % (HMAC_SHA512_RESULT_SIZE - CRYPTO_IV_LENGTH - 1);
hmac[WC_SHA512_DIGEST_SIZE - 1] % (WC_SHA512_DIGEST_SIZE - CRYPTO_IV_LENGTH - 1);
memcpy(&crypto_settings->iv[0], &hmac[offset], CRYPTO_IV_LENGTH);
result = CryptoSeedIVResultFlagSuccess;
@@ -181,4 +186,5 @@ bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings) {
free(decrypted_key);
return key_valid;
}
}
#endif

View File

@@ -1,5 +1,7 @@
#pragma once
#include "../../config/app/config.h"
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
@@ -49,4 +51,5 @@ CryptoSeedIVResult
* @param crypto_settings crypto settings
* @return \c true if cryptographic information is valid; \c false otherwise
*/
bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings);
bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings);
#endif

View File

@@ -0,0 +1,195 @@
#include "crypto_v3.h"
#include <stdlib.h>
#include <furi.h>
#include <furi_hal_crypto.h>
#include <furi_hal_random.h>
#include <furi_hal_version.h>
#include "../../types/common.h"
#include "../../config/wolfssl/config.h"
#include <wolfssl/wolfcrypt/hmac.h>
#include <wolfssl/wolfcrypt/pwdbased.h>
#include "memset_s.h"
#include "constants.h"
#include "polyfills.h"
#define CRYPTO_ALIGNMENT_FACTOR (16)
#define PBKDF2_ITERATIONS_COUNT (200)
static const uint8_t* get_device_uid() {
return (const uint8_t*)UID64_BASE; //-V566
}
static uint8_t get_device_uid_length() {
return furi_hal_version_uid_size();
}
static const uint8_t* get_crypto_verify_key() {
return get_device_uid();
}
static uint8_t get_crypto_verify_key_length() {
return get_device_uid_length();
}
uint8_t* totp_crypto_encrypt_v3(
const uint8_t* plain_data,
const size_t plain_data_length,
const CryptoSettings* crypto_settings,
size_t* encrypted_data_length) {
uint8_t* encrypted_data;
size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR;
if(remain) {
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_check(
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
"Encryption failed: enclave_load_key");
furi_check(
furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length),
"Encryption failed: encrypt");
furi_check(
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
"Encryption failed: enclave_unload_key");
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_check(
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
"Encryption failed: enclave_load_key");
furi_check(
furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length),
"Encryption failed: encrypt");
furi_check(
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
"Encryption failed: enclave_unload_key");
}
return encrypted_data;
}
uint8_t* totp_crypto_decrypt_v3(
const uint8_t* encrypted_data,
const size_t encrypted_data_length,
const CryptoSettings* crypto_settings,
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_check(
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
"Decryption failed: enclave_load_key");
furi_check(
furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length),
"Decryption failed: decrypt");
furi_check(
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
"Decryption failed: enclave_unload_key");
return decrypted_data;
}
CryptoSeedIVResult totp_crypto_seed_iv_v3(
CryptoSettings* crypto_settings,
const uint8_t* pin,
uint8_t pin_length) {
CryptoSeedIVResult result;
if(crypto_settings->crypto_verify_data == NULL) {
FURI_LOG_I(LOGGING_TAG, "Generating new salt");
furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_LENGTH);
}
const uint8_t* device_uid = get_device_uid();
uint8_t device_uid_length = get_device_uid_length();
uint8_t pbkdf_key_length = device_uid_length;
if(pin != NULL && pin_length > 0) {
pbkdf_key_length += pin_length;
}
uint8_t* pbkdf_key = malloc(pbkdf_key_length);
furi_check(pbkdf_key != NULL);
memcpy(pbkdf_key, device_uid, device_uid_length);
if(pin != NULL && pin_length > 0) {
memcpy(pbkdf_key + device_uid_length, pin, pin_length);
}
uint8_t pbkdf_output[WC_SHA512_DIGEST_SIZE] = {0};
int pbkdf_result_code = wc_PBKDF2(
&pbkdf_output[0],
pbkdf_key,
pbkdf_key_length,
&crypto_settings->salt[0],
CRYPTO_SALT_LENGTH,
PBKDF2_ITERATIONS_COUNT,
WC_SHA512_DIGEST_SIZE,
WC_SHA512);
memset_s(pbkdf_key, pbkdf_key_length, 0, pbkdf_key_length);
free(pbkdf_key);
if(pbkdf_result_code == 0) {
uint8_t offset = pbkdf_output[WC_SHA512_DIGEST_SIZE - 1] %
(WC_SHA512_DIGEST_SIZE - CRYPTO_IV_LENGTH - 1);
memcpy(&crypto_settings->iv[0], &pbkdf_output[offset], CRYPTO_IV_LENGTH);
result = CryptoSeedIVResultFlagSuccess;
if(crypto_settings->crypto_verify_data == NULL) {
const uint8_t* crypto_vkey = get_crypto_verify_key();
uint8_t crypto_vkey_length = get_crypto_verify_key_length();
FURI_LOG_I(LOGGING_TAG, "Generating crypto verify data");
crypto_settings->crypto_verify_data = malloc(crypto_vkey_length);
furi_check(crypto_settings->crypto_verify_data != NULL);
crypto_settings->crypto_verify_data_length = crypto_vkey_length;
crypto_settings->crypto_verify_data = totp_crypto_encrypt_v3(
crypto_vkey,
crypto_vkey_length,
crypto_settings,
&crypto_settings->crypto_verify_data_length);
crypto_settings->pin_required = pin != NULL && pin_length > 0;
result |= CryptoSeedIVResultFlagNewCryptoVerifyData;
}
} else {
result = CryptoSeedIVResultFailed;
}
memset_s(&pbkdf_output[0], WC_SHA512_DIGEST_SIZE, 0, WC_SHA512_DIGEST_SIZE);
return result;
}
bool totp_crypto_verify_key_v3(const CryptoSettings* crypto_settings) {
size_t decrypted_key_length;
uint8_t* decrypted_key = totp_crypto_decrypt_v3(
crypto_settings->crypto_verify_data,
crypto_settings->crypto_verify_data_length,
crypto_settings,
&decrypted_key_length);
const uint8_t* crypto_vkey = get_crypto_verify_key();
uint8_t crypto_vkey_length = get_crypto_verify_key_length();
bool key_valid = true;
for(uint8_t i = 0; i < crypto_vkey_length && key_valid; i++) {
if(decrypted_key[i] != crypto_vkey[i]) key_valid = false;
}
free(decrypted_key);
return key_valid;
}

View File

@@ -0,0 +1,52 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "../../types/crypto_settings.h"
#include "common_types.h"
/**
* @brief Encrypts plain data using built-in certificate and given initialization vector (IV)
* @param plain_data plain data to be encrypted
* @param plain_data_length plain data length
* @param crypto_settings crypto settings
* @param[out] encrypted_data_length encrypted data length
* @return Encrypted data
*/
uint8_t* totp_crypto_encrypt_v3(
const uint8_t* plain_data,
const size_t plain_data_length,
const CryptoSettings* crypto_settings,
size_t* encrypted_data_length);
/**
* @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV)
* @param encrypted_data encrypted data to be decrypted
* @param encrypted_data_length encrypted data length
* @param crypto_settings crypto settings
* @param[out] decrypted_data_length decrypted data length
* @return Decrypted data
*/
uint8_t* totp_crypto_decrypt_v3(
const uint8_t* encrypted_data,
const size_t encrypted_data_length,
const CryptoSettings* crypto_settings,
size_t* decrypted_data_length);
/**
* @brief Seed initialization vector (IV) using user's PIN
* @param crypto_settings crypto settings
* @param pin user's PIN
* @param pin_length user's PIN length
* @return Results of seeding IV
*/
CryptoSeedIVResult
totp_crypto_seed_iv_v3(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length);
/**
* @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption
* @param crypto_settings crypto settings
* @return \c true if cryptographic information is valid; \c false otherwise
*/
bool totp_crypto_verify_key_v3(const CryptoSettings* crypto_settings);

View File

@@ -0,0 +1,14 @@
#pragma once
#include <furi_hal_crypto.h>
#ifndef FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_START
// FW Crypto API is outdated, let's polyfill it
#define FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_START (12u)
#define FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_END (100u)
#define furi_hal_crypto_enclave_ensure_key furi_hal_crypto_verify_key
#define furi_hal_crypto_enclave_load_key furi_hal_crypto_store_load_key
#define furi_hal_crypto_enclave_unload_key furi_hal_crypto_store_unload_key
#endif

View File

@@ -1,12 +0,0 @@
#include "byteswap.h"
uint32_t swap_uint32(uint32_t val) {
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
return (val << 16) | (val >> 16);
}
uint64_t swap_uint64(uint64_t val) {
val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL);
val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL);
return (val << 32) | (val >> 32);
}

View File

@@ -1,17 +0,0 @@
#pragma once
#include <stdint.h>
/**
* @brief Swap bytes in 32-bit value
* @param val value to swap bytes in
* @return Value with bytes swapped
*/
uint32_t swap_uint32(uint32_t val);
/**
* @brief Swap bytes in 64-bit value
* @param val value to swap bytes in
* @return Value with bytes swapped
*/
uint64_t swap_uint64(uint64_t val);

View File

@@ -1,59 +0,0 @@
#include <string.h>
#include "memxor.h"
#define IPAD 0x36
#define OPAD 0x5c
/* Concatenate two preprocessor tokens. */
#define _GLHMAC_CONCAT_(prefix, suffix) prefix##suffix
#define _GLHMAC_CONCAT(prefix, suffix) _GLHMAC_CONCAT_(prefix, suffix)
#define HMAC_ALG _GLHMAC_CONCAT(sha, GL_HMAC_NAME)
#define GL_HMAC_CTX _GLHMAC_CONCAT(HMAC_ALG, _ctx)
#define GL_HMAC_FN _GLHMAC_CONCAT(hmac_, HMAC_ALG)
#define GL_HMAC_FN_INIT _GLHMAC_CONCAT(HMAC_ALG, _init_ctx)
#define GL_HMAC_FN_BLOC _GLHMAC_CONCAT(HMAC_ALG, _process_block)
#define GL_HMAC_FN_PROC _GLHMAC_CONCAT(HMAC_ALG, _process_bytes)
#define GL_HMAC_FN_FINI _GLHMAC_CONCAT(HMAC_ALG, _finish_ctx)
static void
hmac_hash(const void* key, size_t keylen, const void* in, size_t inlen, int pad, void* resbuf) {
struct GL_HMAC_CTX hmac_ctx;
char block[GL_HMAC_BLOCKSIZE];
memset(block, pad, sizeof block);
memxor(block, key, keylen);
GL_HMAC_FN_INIT(&hmac_ctx);
GL_HMAC_FN_BLOC(block, sizeof block, &hmac_ctx);
GL_HMAC_FN_PROC(in, inlen, &hmac_ctx);
GL_HMAC_FN_FINI(&hmac_ctx, resbuf);
}
int GL_HMAC_FN(const void* key, size_t keylen, const void* in, size_t inlen, void* resbuf) {
char optkeybuf[GL_HMAC_HASHSIZE];
char innerhash[GL_HMAC_HASHSIZE];
/* Ensure key size is <= block size. */
if(keylen > GL_HMAC_BLOCKSIZE) {
struct GL_HMAC_CTX keyhash;
GL_HMAC_FN_INIT(&keyhash);
GL_HMAC_FN_PROC(key, keylen, &keyhash);
GL_HMAC_FN_FINI(&keyhash, optkeybuf);
key = optkeybuf;
/* zero padding of the key to the block size
is implicit in the memxor. */
keylen = sizeof optkeybuf;
}
/* Compute INNERHASH from KEY and IN. */
hmac_hash(key, keylen, in, inlen, IPAD, innerhash);
/* Compute result from KEY and INNERHASH. */
hmac_hash(key, keylen, innerhash, sizeof innerhash, OPAD, resbuf);
return 0;
}

View File

@@ -1,24 +0,0 @@
/* hmac-sha1.c -- hashed message authentication codes
Copyright (C) 2018-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/>. */
#include "hmac_sha1.h"
#include "sha1.h"
#define GL_HMAC_NAME 1
#define GL_HMAC_BLOCKSIZE 64
#define GL_HMAC_HASHSIZE 20
#include "hmac_common.h"

View File

@@ -1,11 +0,0 @@
#pragma once
#include <stddef.h>
#define HMAC_SHA1_RESULT_SIZE 20
/* Compute Hashed Message Authentication Code with SHA-1, over BUFFER
data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the
output to pre-allocated 20 byte minimum RESBUF buffer. Return 0 on
success. */
int hmac_sha1(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf);

View File

@@ -1,24 +0,0 @@
/* hmac-sha256.c -- hashed message authentication codes
Copyright (C) 2018-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/>. */
#include "hmac_sha256.h"
#include "sha256.h"
#define GL_HMAC_NAME 256
#define GL_HMAC_BLOCKSIZE 64
#define GL_HMAC_HASHSIZE 32
#include "hmac_common.h"

View File

@@ -1,11 +0,0 @@
#pragma once
#include <stddef.h>
#define HMAC_SHA256_RESULT_SIZE 32
/* Compute Hashed Message Authentication Code with SHA-256, over BUFFER
data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the
output to pre-allocated 32 byte minimum RESBUF buffer. Return 0 on
success. */
int hmac_sha256(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf);

View File

@@ -1,24 +0,0 @@
/* hmac-sha512.c -- hashed message authentication codes
Copyright (C) 2018-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/>. */
#include "hmac_sha512.h"
#include "sha512.h"
#define GL_HMAC_NAME 512
#define GL_HMAC_BLOCKSIZE 128
#define GL_HMAC_HASHSIZE 64
#include "hmac_common.h"

View File

@@ -1,11 +0,0 @@
#pragma once
#include <stddef.h>
#define HMAC_SHA512_RESULT_SIZE 64
/* Compute Hashed Message Authentication Code with SHA-512, over BUFFER
data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the
output to pre-allocated 64 byte minimum RESBUF buffer. Return 0 on
success. */
int hmac_sha512(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf);

View File

@@ -1,30 +0,0 @@
/* memxor.c -- perform binary exclusive OR operation of two memory blocks.
Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by Simon Josefsson. The interface was inspired by memxor
in Niels Möller's Nettle. */
#include "memxor.h"
void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) {
char const* s = (char const*)src;
char* d = (char*)dest;
for(; n > 0; n--) *d++ ^= *s++;
return dest;
}

View File

@@ -1,28 +0,0 @@
/* memxor.h -- perform binary exclusive OR operation on memory blocks.
Copyright (C) 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by Simon Josefsson. The interface was inspired by memxor
in Niels Möller's Nettle. */
#pragma once
#include <stddef.h>
/* Compute binary exclusive OR of memory areas DEST and SRC, putting
the result in DEST, of length N bytes. Returns a pointer to
DEST. */
void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n);

View File

@@ -1,251 +0,0 @@
/* sha1.c - Functions to compute SHA1 message digest of files or
memory blocks according to the NIST specification FIPS-180-1.
Copyright (C) 2000-2001, 2003-2006, 2008-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/>. */
/* Written by Scott G. Miller
Credits:
Robert Klep <robert@ilse.nl> -- Expansion function fix
*/
/* Specification. */
#include "sha1.h"
#include <stdint.h>
#include <string.h>
#include "sha_pad_buffer.h"
#ifdef WORDS_BIGENDIAN
#define SWAP(n) (n)
#else
#include "byteswap.h"
#define SWAP(n) swap_uint32(n)
#endif
/* Take a pointer to a 160 bit block of data (five 32 bit ints) and
initialize it to the start constants of the SHA1 algorithm. This
must be called before using hash in the call to sha1_hash. */
void sha1_init_ctx(struct sha1_ctx* ctx) {
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
ctx->C = 0x98badcfe;
ctx->D = 0x10325476;
ctx->E = 0xc3d2e1f0;
ctx->total[0] = ctx->total[1] = 0;
ctx->buflen = 0;
}
/* Copy the 4 byte value from v into the memory location pointed to by *cp,
If your architecture allows unaligned access this is equivalent to
* (uint32_t *) cp = v */
static void set_uint32(char* cp, uint32_t v) {
memcpy(cp, &v, sizeof v);
}
/* Put result from CTX in first 20 bytes following RESBUF. The result
must be in little endian byte order. */
void* sha1_read_ctx(const struct sha1_ctx* ctx, void* resbuf) {
char* r = resbuf;
set_uint32(r + 0 * sizeof ctx->A, SWAP(ctx->A));
set_uint32(r + 1 * sizeof ctx->B, SWAP(ctx->B));
set_uint32(r + 2 * sizeof ctx->C, SWAP(ctx->C));
set_uint32(r + 3 * sizeof ctx->D, SWAP(ctx->D));
set_uint32(r + 4 * sizeof ctx->E, SWAP(ctx->E));
return resbuf;
}
/* Process the remaining bytes in the internal buffer and the usual
prolog according to the standard and write the result to RESBUF. */
void* sha1_finish_ctx(struct sha1_ctx* ctx, void* resbuf) {
/* Take yet unprocessed bytes into account. */
uint32_t bytes = ctx->buflen;
size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
/* Now count remaining bytes. */
ctx->total[0] += bytes;
if(ctx->total[0] < bytes) ++ctx->total[1];
/* Put the 64-bit file length in *bits* at the end of the buffer. */
ctx->buffer[size - 2] = SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29));
ctx->buffer[size - 1] = SWAP(ctx->total[0] << 3);
sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 4 - bytes);
/* Process last bytes. */
sha1_process_block(ctx->buffer, size * 4, ctx);
return sha1_read_ctx(ctx, resbuf);
}
/* Compute SHA1 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. */
void* sha1_buffer(const char* buffer, size_t len, void* resblock) {
struct sha1_ctx ctx;
/* Initialize the computation context. */
sha1_init_ctx(&ctx);
/* Process whole buffer but last len % 64 bytes. */
sha1_process_bytes(buffer, len, &ctx);
/* Put result in desired memory area. */
return sha1_finish_ctx(&ctx, resblock);
}
void sha1_process_bytes(const void* buffer, size_t len, struct sha1_ctx* ctx) {
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
if(ctx->buflen != 0) {
size_t left_over = ctx->buflen;
size_t add = 128 - left_over > len ? len : 128 - left_over;
memcpy(&((char*)ctx->buffer)[left_over], buffer, add);
ctx->buflen += add;
if(ctx->buflen > 64) {
sha1_process_block(ctx->buffer, ctx->buflen & ~63, ctx);
ctx->buflen &= 63;
/* The regions in the following copy operation cannot overlap,
because ctx->buflen < 64 ≤ (left_over + add) & ~63. */
memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~63], ctx->buflen);
}
buffer = (const char*)buffer + add;
len -= add;
}
/* Process available complete blocks. */
if(len >= 64) {
#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned)
#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); //-V1086
buffer = (const char*)buffer + 64;
len -= 64;
}
else
#endif
{
sha1_process_block(buffer, len & ~63, ctx);
buffer = (const char*)buffer + (len & ~63);
len &= 63;
}
}
/* Move remaining bytes in internal buffer. */
if(len > 0) {
size_t left_over = ctx->buflen;
memcpy(&((char*)ctx->buffer)[left_over], buffer, len);
left_over += len;
if(left_over >= 64) {
sha1_process_block(ctx->buffer, 64, ctx);
left_over -= 64;
/* The regions in the following copy operation cannot overlap,
because left_over ≤ 64. */
memcpy(ctx->buffer, &ctx->buffer[16], left_over);
}
ctx->buflen = left_over;
}
}
/* --- Code below is the primary difference between md5.c and sha1.c --- */
/* SHA1 round constants */
static const int sha1_round_constants[4] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
/* Round functions. Note that F2 is the same as F4. */
#define F1(B, C, D) (D ^ (B & (C ^ D)))
#define F2_4(B, C, D) (B ^ C ^ D)
#define F3(B, C, D) ((B & C) | (D & (B | C)))
#define FN(I, B, C, D) (I == 0 ? F1(B, C, D) : (I == 2 ? F3(B, C, D) : F2_4(B, C, D)))
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 64 == 0.
Most of this code comes from GnuPG's cipher/sha1.c. */
void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx) {
const uint32_t* words = buffer;
size_t nwords = len / sizeof(uint32_t);
const uint32_t* endp = words + nwords;
uint32_t x[16];
uint32_t a = ctx->A;
uint32_t b = ctx->B;
uint32_t c = ctx->C;
uint32_t d = ctx->D;
uint32_t e = ctx->E;
uint32_t lolen = len;
/* First increment the byte count. RFC 1321 specifies the possible
length of the file up to 2^64 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] += lolen;
ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen);
#define rol(x, n) (((x) << (n)) | ((uint32_t)(x) >> (32 - (n))))
#define M(I) \
(tm = x[I & 0x0f] ^ x[(I - 14) & 0x0f] ^ x[(I - 8) & 0x0f] ^ x[(I - 3) & 0x0f], \
(x[I & 0x0f] = rol(tm, 1)))
#define R(A, B, C, D, E, F, K, M, KI) \
do { \
E += rol(A, 5) + F(KI, B, C, D) + K + M; \
B = rol(B, 30); \
} while(0)
while(words < endp) {
uint32_t tm;
int t;
for(t = 0; t < 16; t++) {
x[t] = SWAP(*words);
words++;
}
for(uint8_t i = 0; i < 80; i++) {
uint32_t m = i < 16 ? x[i] : M(i);
uint8_t ki = i / 20;
int k_const = sha1_round_constants[ki];
R(a, b, c, d, e, FN, k_const, m, ki);
uint32_t tt = a;
a = e;
e = d;
d = c;
c = b;
b = tt;
}
a = ctx->A += a;
b = ctx->B += b;
c = ctx->C += c;
d = ctx->D += d;
e = ctx->E += e;
}
}
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/

View File

@@ -1,84 +0,0 @@
/* Declarations of functions and data types used for SHA1 sum
library functions.
Copyright (C) 2000-2001, 2003, 2005-2006, 2008-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/>. */
#pragma once
#include <stdio.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SHA1_DIGEST_SIZE 20
/* Structure to save state of computation between the single steps. */
struct sha1_ctx {
uint32_t A;
uint32_t B;
uint32_t C;
uint32_t D;
uint32_t E;
uint32_t total[2];
uint32_t buflen; /* ≥ 0, ≤ 128 */
uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */
};
/* Initialize structure containing state of computation. */
extern void sha1_init_ctx(struct sha1_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is necessary that LEN is a multiple of 64!!! */
extern void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is NOT required that LEN is a multiple of 64. */
extern void sha1_process_bytes(const void* buffer, size_t len, struct sha1_ctx* ctx);
/* Process the remaining bytes in the buffer and put result from CTX
in first 20 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* sha1_finish_ctx(struct sha1_ctx* ctx, void* restrict resbuf);
/* Put result from CTX in first 20 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* sha1_read_ctx(const struct sha1_ctx* ctx, void* restrict resbuf);
/* Compute SHA1 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* sha1_buffer(const char* buffer, size_t len, void* restrict resblock);
#ifdef __cplusplus
}
#endif
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/

View File

@@ -1,283 +0,0 @@
/* 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.
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/>. */
/* Written by David Madore, considerably copypasting from
Scott G. Miller's sha1.c
*/
/* Specification. */
#include "sha256.h"
#include <stdint.h>
#include <string.h>
#include "sha_pad_buffer.h"
#ifdef WORDS_BIGENDIAN
#define SWAP(n) (n)
#else
#include "byteswap.h"
#define SWAP(n) swap_uint32(n)
#endif
/*
Takes a pointer to a 256 bit block of data (eight 32 bit ints) and
initializes it to the start constants of the SHA256 algorithm. This
must be called before using hash in the call to sha256_hash
*/
void sha256_init_ctx(struct sha256_ctx* ctx) {
ctx->state[0] = 0x6a09e667UL;
ctx->state[1] = 0xbb67ae85UL;
ctx->state[2] = 0x3c6ef372UL;
ctx->state[3] = 0xa54ff53aUL;
ctx->state[4] = 0x510e527fUL;
ctx->state[5] = 0x9b05688cUL;
ctx->state[6] = 0x1f83d9abUL;
ctx->state[7] = 0x5be0cd19UL;
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 */
static void set_uint32(char* cp, uint32_t v) {
memcpy(cp, &v, sizeof v);
}
/* Put result from CTX in first 32 bytes following RESBUF.
The result must be in little endian byte order. */
void* sha256_read_ctx(const struct sha256_ctx* ctx, void* resbuf) {
int i;
char* r = resbuf;
for(i = 0; i < 8; 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) {
/* Take yet unprocessed bytes into account. */
size_t bytes = ctx->buflen;
size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
/* Now count remaining bytes. */
ctx->total[0] += bytes;
if(ctx->total[0] < bytes) ++ctx->total[1];
/* Put the 64-bit file length in *bits* at the end of the buffer.
Use set_uint32 rather than a simple assignment, to avoid risk of
unaligned access. */
set_uint32((char*)&ctx->buffer[size - 2], SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29)));
set_uint32((char*)&ctx->buffer[size - 1], SWAP(ctx->total[0] << 3));
sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 4 - bytes);
/* Process last bytes. */
sha256_process_block(ctx->buffer, size * 4, ctx);
}
void* sha256_finish_ctx(struct sha256_ctx* ctx, void* resbuf) {
sha256_conclude_ctx(ctx);
return sha256_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
digest. */
void* sha256_buffer(const char* buffer, size_t len, void* resblock) {
struct sha256_ctx ctx;
/* Initialize the computation context. */
sha256_init_ctx(&ctx);
/* Process whole buffer but last len % 64 bytes. */
sha256_process_bytes(buffer, len, &ctx);
/* Put result in desired memory area. */
return sha256_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. */
if(ctx->buflen != 0) {
size_t left_over = ctx->buflen;
size_t add = 128 - left_over > len ? len : 128 - left_over;
memcpy(&((char*)ctx->buffer)[left_over], buffer, add);
ctx->buflen += add;
if(ctx->buflen > 64) {
sha256_process_block(ctx->buffer, ctx->buflen & ~63, ctx);
ctx->buflen &= 63;
/* The regions in the following copy operation cannot overlap,
because ctx->buflen < 64 ≤ (left_over + add) & ~63. */
memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~63], ctx->buflen);
}
buffer = (const char*)buffer + add;
len -= add;
}
/* Process available complete blocks. */
if(len >= 64) {
#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned)
#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); //-V1086
buffer = (const char*)buffer + 64;
len -= 64;
}
else
#endif
{
sha256_process_block(buffer, len & ~63, ctx);
buffer = (const char*)buffer + (len & ~63);
len &= 63;
}
}
/* Move remaining bytes in internal buffer. */
if(len > 0) {
size_t left_over = ctx->buflen;
memcpy(&((char*)ctx->buffer)[left_over], buffer, len);
left_over += len;
if(left_over >= 64) {
sha256_process_block(ctx->buffer, 64, ctx);
left_over -= 64;
/* The regions in the following copy operation cannot overlap,
because left_over ≤ 64. */
memcpy(ctx->buffer, &ctx->buffer[16], left_over);
}
ctx->buflen = left_over;
}
}
/* --- Code below is the primary difference between sha1.c and sha256.c --- */
/* SHA256 round constants */
#define K(I) sha256_round_constants[I]
static const uint32_t sha256_round_constants[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL,
0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL,
0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL,
0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL,
0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
};
/* Round functions. */
#define F2(A, B, C) ((A & B) | (C & (A | B)))
#define F1(E, F, G) (G ^ (E & (F ^ G)))
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 64 == 0.
Most of this code comes from GnuPG's cipher/sha1.c. */
void sha256_process_block(const void* buffer, size_t len, struct sha256_ctx* ctx) {
const uint32_t* words = buffer;
size_t nwords = len / sizeof(uint32_t);
const uint32_t* endp = words + nwords;
uint32_t x[16];
uint32_t a = ctx->state[0];
uint32_t b = ctx->state[1];
uint32_t c = ctx->state[2];
uint32_t d = ctx->state[3];
uint32_t e = ctx->state[4];
uint32_t f = ctx->state[5];
uint32_t g = ctx->state[6];
uint32_t h = ctx->state[7];
uint32_t lolen = len;
/* First increment the byte count. FIPS PUB 180-2 specifies the possible
length of the file up to 2^64 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] += lolen;
ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen);
#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define S0(x) (rol(x, 25) ^ rol(x, 14) ^ (x >> 3))
#define S1(x) (rol(x, 15) ^ rol(x, 13) ^ (x >> 10))
#define SS0(x) (rol(x, 30) ^ rol(x, 19) ^ rol(x, 10))
#define SS1(x) (rol(x, 26) ^ rol(x, 21) ^ rol(x, 7))
#define M(I) \
(tm = S1(x[(I - 2) & 0x0f]) + x[(I - 7) & 0x0f] + S0(x[(I - 15) & 0x0f]) + x[I & 0x0f], \
x[I & 0x0f] = tm)
#define R(A, B, C, D, E, F, G, H, K, M) \
do { \
t0 = SS0(A) + F2(A, B, C); \
t1 = H + SS1(E) + F1(E, F, G) + K + M; \
D += t1; \
H = t0 + t1; \
} while(0)
while(words < endp) {
uint32_t tm;
uint32_t t0, t1;
int t;
/* FIXME: see sha1.c for a better implementation. */
for(t = 0; t < 16; t++) {
x[t] = SWAP(*words);
words++;
}
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;
c = ctx->state[2] += c;
d = ctx->state[3] += d;
e = ctx->state[4] += e;
f = ctx->state[5] += f;
g = ctx->state[6] += g;
h = ctx->state[7] += h;
}
}
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/

View File

@@ -1,79 +0,0 @@
/* Declarations of functions and data types used for SHA256 sum
library functions.
Copyright (C) 2005-2006, 2008-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/>. */
#pragma once
#include <stdio.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
enum { SHA256_DIGEST_SIZE = 256 / 8 };
/* Structure to save state of computation between the single steps. */
struct sha256_ctx {
uint32_t state[8];
uint32_t total[2];
size_t buflen; /* ≥ 0, ≤ 128 */
uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */
};
/* Initialize structure containing state of computation. */
extern void sha256_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
starting at BUFFER.
It is necessary that LEN is a multiple of 64!!! */
extern void sha256_process_block(const void* buffer, size_t len, 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
starting at BUFFER.
It is NOT required that LEN is a multiple of 64. */
extern void sha256_process_bytes(const void* buffer, size_t len, struct sha256_ctx* ctx);
/* Process the remaining bytes in the buffer and 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_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);
/* 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);
#ifdef __cplusplus
}
#endif
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/

View File

@@ -1,309 +0,0 @@
/* 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.
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/>. */
/* Written by David Madore, considerably copypasting from
Scott G. Miller's sha1.c
*/
/* Specification. */
#include "sha512.h"
#include <stdint.h>
#include <string.h>
#include "byteswap.h"
#include "sha_pad_buffer.h"
#define SWAP(n) swap_uint64(n)
/*
Takes a pointer to a 512 bit block of data (eight 64 bit ints) and
initializes it to the start constants of the SHA512 algorithm. This
must be called before using hash in the call to sha512_hash
*/
void sha512_init_ctx(struct sha512_ctx* ctx) {
ctx->state[0] = u64hilo(0x6a09e667, 0xf3bcc908);
ctx->state[1] = u64hilo(0xbb67ae85, 0x84caa73b);
ctx->state[2] = u64hilo(0x3c6ef372, 0xfe94f82b);
ctx->state[3] = u64hilo(0xa54ff53a, 0x5f1d36f1);
ctx->state[4] = u64hilo(0x510e527f, 0xade682d1);
ctx->state[5] = u64hilo(0x9b05688c, 0x2b3e6c1f);
ctx->state[6] = u64hilo(0x1f83d9ab, 0xfb41bd6b);
ctx->state[7] = u64hilo(0x5be0cd19, 0x137e2179);
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 */
static void set_uint64(char* cp, u64 v) {
memcpy(cp, &v, sizeof v);
}
/* Put result from CTX in first 64 bytes following RESBUF.
The result must be in little endian byte order. */
void* sha512_read_ctx(const struct sha512_ctx* ctx, void* resbuf) {
int i;
char* r = resbuf;
for(i = 0; i < 8; 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) {
/* Take yet unprocessed bytes into account. */
size_t bytes = ctx->buflen;
size_t size = (bytes < 112) ? 128 / 8 : 128 * 2 / 8;
/* Now count remaining bytes. */
ctx->total[0] = u64plus(ctx->total[0], u64lo(bytes));
if(u64lt(ctx->total[0], u64lo(bytes))) ctx->total[1] = u64plus(ctx->total[1], u64lo(1));
/* Put the 128-bit file length in *bits* at the end of the buffer.
Use set_uint64 rather than a simple assignment, to avoid risk of
unaligned access. */
set_uint64(
(char*)&ctx->buffer[size - 2],
SWAP(u64or(u64shl(ctx->total[1], 3), u64shr(ctx->total[0], 61))));
set_uint64((char*)&ctx->buffer[size - 1], SWAP(u64shl(ctx->total[0], 3)));
sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 8 - bytes);
/* Process last bytes. */
sha512_process_block(ctx->buffer, size * 8, ctx);
}
void* sha512_finish_ctx(struct sha512_ctx* ctx, void* resbuf) {
sha512_conclude_ctx(ctx);
return sha512_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
digest. */
void* sha512_buffer(const char* buffer, size_t len, void* resblock) {
struct sha512_ctx ctx;
/* Initialize the computation context. */
sha512_init_ctx(&ctx);
/* Process whole buffer but last len % 128 bytes. */
sha512_process_bytes(buffer, len, &ctx);
/* Put result in desired memory area. */
return sha512_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. */
if(ctx->buflen != 0) {
size_t left_over = ctx->buflen;
size_t add = 256 - left_over > len ? len : 256 - left_over;
memcpy(&((char*)ctx->buffer)[left_over], buffer, add);
ctx->buflen += add;
if(ctx->buflen > 128) {
sha512_process_block(ctx->buffer, ctx->buflen & ~127, ctx);
ctx->buflen &= 127;
/* The regions in the following copy operation cannot overlap,
because ctx->buflen < 128 ≤ (left_over + add) & ~127. */
memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~127], ctx->buflen);
}
buffer = (const char*)buffer + add;
len -= add;
}
/* Process available complete blocks. */
if(len >= 128) {
#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned)
#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); //-V1086
buffer = (const char*)buffer + 128;
len -= 128;
}
else
#endif
{
sha512_process_block(buffer, len & ~127, ctx);
buffer = (const char*)buffer + (len & ~127);
len &= 127;
}
}
/* Move remaining bytes in internal buffer. */
if(len > 0) {
size_t left_over = ctx->buflen;
memcpy(&((char*)ctx->buffer)[left_over], buffer, len);
left_over += len;
if(left_over >= 128) {
sha512_process_block(ctx->buffer, 128, ctx);
left_over -= 128;
/* The regions in the following copy operation cannot overlap,
because left_over ≤ 128. */
memcpy(ctx->buffer, &ctx->buffer[16], left_over);
}
ctx->buflen = left_over;
}
}
/* --- Code below is the primary difference between sha1.c and sha512.c --- */
/* SHA512 round constants */
#define K(I) sha512_round_constants[I]
static u64 const sha512_round_constants[80] = {
u64init(0x428a2f98, 0xd728ae22), u64init(0x71374491, 0x23ef65cd),
u64init(0xb5c0fbcf, 0xec4d3b2f), u64init(0xe9b5dba5, 0x8189dbbc),
u64init(0x3956c25b, 0xf348b538), u64init(0x59f111f1, 0xb605d019),
u64init(0x923f82a4, 0xaf194f9b), u64init(0xab1c5ed5, 0xda6d8118),
u64init(0xd807aa98, 0xa3030242), u64init(0x12835b01, 0x45706fbe),
u64init(0x243185be, 0x4ee4b28c), u64init(0x550c7dc3, 0xd5ffb4e2),
u64init(0x72be5d74, 0xf27b896f), u64init(0x80deb1fe, 0x3b1696b1),
u64init(0x9bdc06a7, 0x25c71235), u64init(0xc19bf174, 0xcf692694),
u64init(0xe49b69c1, 0x9ef14ad2), u64init(0xefbe4786, 0x384f25e3),
u64init(0x0fc19dc6, 0x8b8cd5b5), u64init(0x240ca1cc, 0x77ac9c65),
u64init(0x2de92c6f, 0x592b0275), u64init(0x4a7484aa, 0x6ea6e483),
u64init(0x5cb0a9dc, 0xbd41fbd4), u64init(0x76f988da, 0x831153b5),
u64init(0x983e5152, 0xee66dfab), u64init(0xa831c66d, 0x2db43210),
u64init(0xb00327c8, 0x98fb213f), u64init(0xbf597fc7, 0xbeef0ee4),
u64init(0xc6e00bf3, 0x3da88fc2), u64init(0xd5a79147, 0x930aa725),
u64init(0x06ca6351, 0xe003826f), u64init(0x14292967, 0x0a0e6e70),
u64init(0x27b70a85, 0x46d22ffc), u64init(0x2e1b2138, 0x5c26c926),
u64init(0x4d2c6dfc, 0x5ac42aed), u64init(0x53380d13, 0x9d95b3df),
u64init(0x650a7354, 0x8baf63de), u64init(0x766a0abb, 0x3c77b2a8),
u64init(0x81c2c92e, 0x47edaee6), u64init(0x92722c85, 0x1482353b),
u64init(0xa2bfe8a1, 0x4cf10364), u64init(0xa81a664b, 0xbc423001),
u64init(0xc24b8b70, 0xd0f89791), u64init(0xc76c51a3, 0x0654be30),
u64init(0xd192e819, 0xd6ef5218), u64init(0xd6990624, 0x5565a910),
u64init(0xf40e3585, 0x5771202a), u64init(0x106aa070, 0x32bbd1b8),
u64init(0x19a4c116, 0xb8d2d0c8), u64init(0x1e376c08, 0x5141ab53),
u64init(0x2748774c, 0xdf8eeb99), u64init(0x34b0bcb5, 0xe19b48a8),
u64init(0x391c0cb3, 0xc5c95a63), u64init(0x4ed8aa4a, 0xe3418acb),
u64init(0x5b9cca4f, 0x7763e373), u64init(0x682e6ff3, 0xd6b2b8a3),
u64init(0x748f82ee, 0x5defb2fc), u64init(0x78a5636f, 0x43172f60),
u64init(0x84c87814, 0xa1f0ab72), u64init(0x8cc70208, 0x1a6439ec),
u64init(0x90befffa, 0x23631e28), u64init(0xa4506ceb, 0xde82bde9),
u64init(0xbef9a3f7, 0xb2c67915), u64init(0xc67178f2, 0xe372532b),
u64init(0xca273ece, 0xea26619c), u64init(0xd186b8c7, 0x21c0c207),
u64init(0xeada7dd6, 0xcde0eb1e), u64init(0xf57d4f7f, 0xee6ed178),
u64init(0x06f067aa, 0x72176fba), u64init(0x0a637dc5, 0xa2c898a6),
u64init(0x113f9804, 0xbef90dae), u64init(0x1b710b35, 0x131c471b),
u64init(0x28db77f5, 0x23047d84), u64init(0x32caab7b, 0x40c72493),
u64init(0x3c9ebe0a, 0x15c9bebc), u64init(0x431d67c4, 0x9c100d4c),
u64init(0x4cc5d4be, 0xcb3e42b6), u64init(0x597f299c, 0xfc657e2a),
u64init(0x5fcb6fab, 0x3ad6faec), u64init(0x6c44198c, 0x4a475817),
};
/* Round functions. */
#define F2(A, B, C) u64or(u64and(A, B), u64and(C, u64or(A, B)))
#define F1(E, F, G) u64xor(G, u64and(E, u64xor(F, G)))
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 128 == 0.
Most of this code comes from GnuPG's cipher/sha1.c. */
void sha512_process_block(const void* buffer, size_t len, struct sha512_ctx* ctx) {
u64 const* words = buffer;
u64 const* endp = words + len / sizeof(u64);
u64 x[16];
u64 a = ctx->state[0];
u64 b = ctx->state[1];
u64 c = ctx->state[2];
u64 d = ctx->state[3];
u64 e = ctx->state[4];
u64 f = ctx->state[5];
u64 g = ctx->state[6];
u64 h = ctx->state[7];
u64 lolen = u64size(len);
/* First increment the byte count. FIPS PUB 180-2 specifies the possible
length of the file up to 2^128 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] = u64plus(ctx->total[0], lolen);
ctx->total[1] = u64plus(
ctx->total[1], u64plus(u64size(len >> 31 >> 31 >> 2), u64lo(u64lt(ctx->total[0], lolen))));
#define S0(x) u64xor(u64rol(x, 63), u64xor(u64rol(x, 56), u64shr(x, 7)))
#define S1(x) u64xor(u64rol(x, 45), u64xor(u64rol(x, 3), u64shr(x, 6)))
#define SS0(x) u64xor(u64rol(x, 36), u64xor(u64rol(x, 30), u64rol(x, 25)))
#define SS1(x) u64xor(u64rol(x, 50), u64xor(u64rol(x, 46), u64rol(x, 23)))
#define M(I) \
(x[(I)&15] = u64plus( \
x[(I)&15], \
u64plus(S1(x[((I)-2) & 15]), u64plus(x[((I)-7) & 15], S0(x[((I)-15) & 15])))))
#define R(A, B, C, D, E, F, G, H, K, M) \
do { \
u64 t0 = u64plus(SS0(A), F2(A, B, C)); \
u64 t1 = u64plus(H, u64plus(SS1(E), u64plus(F1(E, F, G), u64plus(K, M)))); \
D = u64plus(D, t1); \
H = u64plus(t0, t1); \
} while(0)
while(words < endp) {
int t;
/* FIXME: see sha1.c for a better implementation. */
for(t = 0; t < 16; t++) {
x[t] = SWAP(*words);
words++;
}
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);
c = ctx->state[2] = u64plus(ctx->state[2], c);
d = ctx->state[3] = u64plus(ctx->state[3], d);
e = ctx->state[4] = u64plus(ctx->state[4], e);
f = ctx->state[5] = u64plus(ctx->state[5], f);
g = ctx->state[6] = u64plus(ctx->state[6], g);
h = ctx->state[7] = u64plus(ctx->state[7], h);
}
}
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/

View File

@@ -1,82 +0,0 @@
/* Declarations of functions and data types used for SHA512 and SHA384 sum
library functions.
Copyright (C) 2005-2006, 2008-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/>. */
#pragma once
#include <stdio.h>
#include "u64.h"
#ifdef __cplusplus
extern "C" {
#endif
enum { SHA512_DIGEST_SIZE = 512 / 8 };
/* Structure to save state of computation between the single steps. */
struct sha512_ctx {
u64 state[8];
u64 total[2];
size_t buflen; /* ≥ 0, ≤ 256 */
u64 buffer[32]; /* 256 bytes; the first buflen bytes are in use */
};
/* Initialize structure containing state of computation. */
extern void sha512_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
starting at BUFFER.
It is necessary that LEN is a multiple of 128!!! */
extern void sha512_process_block(const void* buffer, size_t len, 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
starting at BUFFER.
It is NOT required that LEN is a multiple of 128. */
extern void sha512_process_bytes(const void* buffer, size_t len, struct sha512_ctx* ctx);
/* Process the remaining bytes in the buffer and 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 to the wanted
ASCII representation of the message digest. */
extern void* sha512_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
to the wanted ASCII representation of the message digest.
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);
/* 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);
#ifdef __cplusplus
}
#endif
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/

View File

@@ -1,11 +0,0 @@
#include "sha_pad_buffer.h"
#include <string.h>
void sha_pad_buffer(uint8_t* buffer, size_t size) {
if(size > 0) {
buffer[0] = 0x80;
if(size > 1) {
memset(&buffer[1], 0, size - 1);
}
}
}

View File

@@ -1,4 +0,0 @@
#include <stddef.h>
#include <stdint.h>
void sha_pad_buffer(uint8_t* buffer, size_t size);

View File

@@ -1,44 +0,0 @@
/* uint64_t-like operations that work even on hosts lacking uint64_t
Copyright (C) 2006, 2009-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/>. */
/* Written by Paul Eggert. */
#pragma once
#include <stdint.h>
#ifndef _GL_U64_INLINE
#define _GL_U64_INLINE _GL_INLINE
#endif
/* Return X rotated left by N bits, where 0 < N < 64. */
#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. */
typedef uint64_t u64;
#define u64hilo(hi, lo) ((u64)(((u64)(hi) << 32) + (lo)))
#define u64init(hi, lo) u64hilo(hi, lo)
#define u64lo(x) ((u64)(x))
#define u64size(x) u64lo(x)
#define u64lt(x, y) ((x) < (y))
#define u64and(x, y) ((x) & (y))
#define u64or(x, y) ((x) | (y))
#define u64xor(x, y) ((x) ^ (y))
#define u64plus(x, y) ((x) + (y))
#define u64shl(x, n) ((x) << (n))
#define u64shr(x, n) ((x) >> (n))

View File

@@ -4,12 +4,16 @@
#include <stdint.h>
#include <math.h>
#include <timezone_utils.h>
#include "../hmac/hmac_sha1.h"
#include "../hmac/hmac_sha256.h"
#include "../hmac/hmac_sha512.h"
#include "../hmac/byteswap.h"
#include "../../config/wolfssl/config.h"
#include <wolfssl/wolfcrypt/hmac.h>
#define HMAC_MAX_RESULT_SIZE HMAC_SHA512_RESULT_SIZE
#define HMAC_MAX_RESULT_SIZE WC_SHA512_DIGEST_SIZE
static uint64_t swap_uint64(uint64_t val) {
val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL);
val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL);
return (val << 32) | (val >> 32);
}
/**
* @brief Generates the timeblock for a time in seconds.
@@ -68,14 +72,34 @@ uint64_t totp_at(
algo, plain_secret, plain_secret_length, totp_timecode(interval, for_time_adjusted));
}
static int totp_algo_common(
int type,
const uint8_t* key,
size_t key_length,
const uint8_t* input,
size_t input_length,
uint8_t* output) {
Hmac hmac;
int ret = wc_HmacSetKey(&hmac, type, key, key_length);
if(ret == 0) {
ret = wc_HmacUpdate(&hmac, input, input_length);
}
if(ret == 0) {
ret = wc_HmacFinal(&hmac, output);
}
wc_HmacFree(&hmac);
return ret == 0 ? wc_HmacSizeByType(type) : 0;
}
static int totp_algo_sha1(
const uint8_t* key,
size_t key_length,
const uint8_t* input,
size_t input_length,
uint8_t* output) {
hmac_sha1(key, key_length, input, input_length, output);
return HMAC_SHA1_RESULT_SIZE;
return totp_algo_common(WC_SHA, key, key_length, input, input_length, output);
}
static int totp_algo_sha256(
@@ -84,8 +108,7 @@ static int totp_algo_sha256(
const uint8_t* input,
size_t input_length,
uint8_t* output) {
hmac_sha256(key, key_length, input, input_length, output);
return HMAC_SHA256_RESULT_SIZE;
return totp_algo_common(WC_SHA256, key, key_length, input, input_length, output);
}
static int totp_algo_sha512(
@@ -94,8 +117,7 @@ static int totp_algo_sha512(
const uint8_t* input,
size_t input_length,
uint8_t* output) {
hmac_sha512(key, key_length, input, input_length, output);
return HMAC_SHA512_RESULT_SIZE;
return totp_algo_common(WC_SHA512, key, key_length, input, input_length, output);
}
const TOTP_ALGO TOTP_ALGO_SHA1 = (TOTP_ALGO)(&totp_algo_sha1);

View File

@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include "features_config.h"
#include "config/app/config.h"
#include "services/config/config.h"
#include "types/plugin_state.h"
#include "types/token_info.h"
@@ -17,6 +17,7 @@
#include "services/crypto/crypto_facade.h"
#include "cli/cli.h"
#include "version.h"
#include <wolfssl/version.h>
struct TotpRenderCallbackContext {
FuriMutex* mutex;
@@ -217,6 +218,8 @@ int32_t totp_app() {
TOTP_APP_VERSION_MAJOR,
TOTP_APP_VERSION_MINOR,
TOTP_APP_VERSION_PATCH);
FURI_LOG_I(LOGGING_TAG, "WolfSSL version: " LIBWOLFSSL_VERSION_STRING);
PluginState* plugin_state = malloc(sizeof(PluginState));
furi_check(plugin_state != NULL);

View File

@@ -1,6 +1,6 @@
#pragma once
#include "../features_config.h"
#include "../config/app/config.h"
typedef uint8_t AutomationMethod;

View File

@@ -20,9 +20,9 @@ typedef struct {
uint8_t iv[CRYPTO_IV_LENGTH];
/**
* @brief Basic randomly-generated initialization vector (IV)
* @brief Randomly-generated salt
*/
uint8_t base_iv[CRYPTO_IV_LENGTH];
uint8_t salt[CRYPTO_SALT_LENGTH];
/**
* @brief Encrypted well-known data

View File

@@ -3,7 +3,7 @@
#include <notification/notification.h>
#include <gui/gui.h>
#include <dialogs/dialogs.h>
#include "../features_config.h"
#include "../config/app/config.h"
#include "../ui/totp_scenes_enum.h"
#include "../services/config/config_file_context.h"
#include "../services/idle_timeout/idle_timeout.h"

View File

@@ -1,8 +1,11 @@
#include "../types/common.h"
#include "../config/app/config.h"
#include "scene_director.h"
#include "scenes/authenticate/totp_scene_authenticate.h"
#include "scenes/generate_token/totp_scene_generate_token.h"
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
#include "scenes/add_new_token/totp_scene_add_new_token.h"
#endif
#include "scenes/token_menu/totp_scene_token_menu.h"
#include "scenes/app_settings/totp_app_settings.h"
#include "scenes/standby/standby.h"
@@ -16,9 +19,11 @@ void totp_scene_director_activate_scene(PluginState* const plugin_state, Scene s
case TotpSceneAuthentication:
totp_scene_authenticate_activate(plugin_state);
break;
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
case TotpSceneAddNewToken:
totp_scene_add_new_token_activate(plugin_state);
break;
#endif
case TotpSceneTokenMenu:
totp_scene_token_menu_activate(plugin_state);
break;
@@ -45,9 +50,11 @@ void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state
case TotpSceneAuthentication:
totp_scene_authenticate_deactivate(plugin_state);
break;
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
case TotpSceneAddNewToken:
totp_scene_add_new_token_deactivate(plugin_state);
break;
#endif
case TotpSceneTokenMenu:
totp_scene_token_menu_deactivate(plugin_state);
break;
@@ -70,9 +77,11 @@ void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_
case TotpSceneAuthentication:
totp_scene_authenticate_render(canvas, plugin_state);
break;
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
case TotpSceneAddNewToken:
totp_scene_add_new_token_render(canvas, plugin_state);
break;
#endif
case TotpSceneTokenMenu:
totp_scene_token_menu_render(canvas, plugin_state);
break;
@@ -98,9 +107,11 @@ bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* con
case TotpSceneAuthentication:
processing = totp_scene_authenticate_handle_event(event, plugin_state);
break;
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
case TotpSceneAddNewToken:
processing = totp_scene_add_new_token_handle_event(event, plugin_state);
break;
#endif
case TotpSceneTokenMenu:
processing = totp_scene_token_menu_handle_event(event, plugin_state);
break;

View File

@@ -1,5 +1,6 @@
#include "totp_input_text.h"
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
#include <gui/view_dispatcher.h>
#include <gui/modules/text_input.h>
@@ -50,3 +51,4 @@ void totp_input_text(Gui* gui, const char* header_text, InputTextResult* result)
view_dispatcher_free(view_dispatcher);
text_input_free(text_input);
}
#endif

View File

@@ -1,5 +1,7 @@
#pragma once
#include "../../../config/app/config.h"
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
#include <gui/gui.h>
#define INPUT_BUFFER_SIZE (255)
@@ -11,3 +13,4 @@ typedef struct {
} InputTextResult;
void totp_input_text(Gui* gui, const char* header_text, InputTextResult* result);
#endif

View File

@@ -1,4 +1,5 @@
#include "totp_scene_add_new_token.h"
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
#include "../../../types/common.h"
#include "../../constants.h"
#include "../../scene_director.h"
@@ -8,7 +9,6 @@
#include "../../ui_controls.h"
#include "../../common_dialogs.h"
#include <roll_value.h>
#include "../generate_token/totp_scene_generate_token.h"
char* TOKEN_ALGO_LIST[] = {"SHA1", "SHA256", "SHA512", "Steam"};
char* TOKEN_DIGITS_TEXT_LIST[] = {"5 digits", "6 digits", "8 digits"};
@@ -318,3 +318,4 @@ void totp_scene_add_new_token_deactivate(PluginState* plugin_state) {
free(plugin_state->current_scene_state);
plugin_state->current_scene_state = NULL;
}
#endif

View File

@@ -1,5 +1,7 @@
#pragma once
#include "../../../config/app/config.h"
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
#include <gui/gui.h>
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
@@ -10,3 +12,4 @@ bool totp_scene_add_new_token_handle_event(
const PluginEvent* const event,
PluginState* plugin_state);
void totp_scene_add_new_token_deactivate(PluginState* plugin_state);
#endif

View File

@@ -1,18 +1,16 @@
#include "totp_app_settings.h"
#include <math.h>
#include <totp_icons.h>
#include <assets_icons.h>
#include <available_fonts.h>
#include "../../canvas_extensions.h"
#include "../../ui_controls.h"
#include "../../common_dialogs.h"
#include "../../scene_director.h"
#include "../token_menu/totp_scene_token_menu.h"
#include "../../constants.h"
#include "../../../services/config/config.h"
#include "../../../services/convert/convert.h"
#include <roll_value.h>
#include "../../../features_config.h"
#include "../../../config/app/config.h"
#ifdef TOTP_BADBT_AUTOMATION_ENABLED
#include "../../../workers/bt_type_code/bt_type_code.h"
#endif

View File

@@ -1,3 +1,4 @@
#include "totp_scene_generate_token.h"
#include <gui/gui.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
@@ -5,15 +6,13 @@
#include <assets_icons.h>
#include <roll_value.h>
#include <available_fonts.h>
#include "totp_scene_generate_token.h"
#include "../../canvas_extensions.h"
#include "../../../types/token_info.h"
#include "../../../types/common.h"
#include "../../constants.h"
#include "../../../services/config/config.h"
#include "../../scene_director.h"
#include "../token_menu/totp_scene_token_menu.h"
#include "../../../features_config.h"
#include "../../../config/app/config.h"
#include "../../../workers/generate_totp_code/generate_totp_code.h"
#include "../../../workers/usb_type_code/usb_type_code.h"
#ifdef TOTP_BADBT_AUTOMATION_ENABLED
@@ -247,7 +246,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
SCREEN_HEIGHT_CENTER + 10,
AlignCenter,
AlignCenter,
"Press OK button to add");
"Press OK button to access menu");
return;
}

View File

@@ -7,9 +7,7 @@
#include "../../scene_director.h"
#include "../../../services/config/config.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 "../../../config/app/config.h"
#include <roll_value.h>
#define SCREEN_HEIGHT_THIRD (SCREEN_HEIGHT / 3)
@@ -130,7 +128,22 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt
} else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) {
switch(scene_state->selected_control) {
case AddNewToken: {
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
totp_scene_director_activate_scene(plugin_state, TotpSceneAddNewToken);
#else
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "Back", NULL, NULL);
dialog_message_set_header(message, "Information", 0, 0, AlignLeft, AlignTop);
dialog_message_set_text(
message,
"Read here\nhttps://t.ly/8ZOtj\n how to add new token",
SCREEN_WIDTH_CENTER,
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
dialog_message_show(plugin_state->dialogs_app, message);
dialog_message_free(message);
#endif
break;
}
case DeleteToken: {

View File

@@ -1,5 +1,7 @@
#pragma once
#include "../config/app/config.h"
typedef uint8_t Scene;
/**
@@ -21,10 +23,12 @@ enum Scenes {
*/
TotpSceneGenerateToken,
#ifdef TOTP_UI_ADD_NEW_TOKEN_ENABLED
/**
* @brief Scene where user can add new token
*/
TotpSceneAddNewToken,
#endif
/**
* @brief Scene with a menu for given token, allowing user to do multiple actions

View File

@@ -1,5 +1,5 @@
#pragma once
#define TOTP_APP_VERSION_MAJOR (3)
#define TOTP_APP_VERSION_MINOR (2)
#define TOTP_APP_VERSION_PATCH (0)
#define TOTP_APP_VERSION_MAJOR (4)
#define TOTP_APP_VERSION_MINOR (0)
#define TOTP_APP_VERSION_PATCH (1)

View File

@@ -11,7 +11,8 @@
#include "../../types/common.h"
#include "../../types/token_info.h"
#include "../type_code_common.h"
#include "../../features_config.h"
#include "../../config/app/config.h"
#include "../../services/config/constants.h"
#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL
#define TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH

View File

@@ -4,7 +4,6 @@
#include <stdbool.h>
#include <furi/core/mutex.h>
#include "../../types/automation_kb_layout.h"
#include "../../services/config/constants.h"
#define TOTP_BT_KEYS_STORAGE_PATH EXT_PATH("apps_data/totp/.bt_hid.keys")