TOTP Update - "BadUSB" type key into pc mode

This commit is contained in:
MX 2022-11-11 01:10:45 +03:00
parent f6eed35729
commit 64774f191f
No known key found for this signature in database
GPG key ID: 6C4C311DFD4B4AB5
4 changed files with 168 additions and 5 deletions

View file

@ -13,19 +13,21 @@
#include "../../services/roll_value/roll_value.h" #include "../../services/roll_value/roll_value.h"
#include "../scene_director.h" #include "../scene_director.h"
#include "../token_menu/totp_scene_token_menu.h" #include "../token_menu/totp_scene_token_menu.h"
#include "../../services/hid_worker/hid_worker.h"
#define TOKEN_LIFETIME 30 #define TOKEN_LIFETIME 30
#define DIGIT_TO_CHAR(digit) ((digit) + '0') #define DIGIT_TO_CHAR(digit) ((digit) + '0')
typedef struct { typedef struct {
uint16_t current_token_index; uint16_t current_token_index;
char last_code[9]; char last_code[TOTP_TOKEN_DIGITS_MAX_COUNT + 1];
char* last_code_name; char* last_code_name;
bool need_token_update; bool need_token_update;
uint32_t last_token_gen_time; uint32_t last_token_gen_time;
TotpHidWorkerTypeContext* hid_worker_context;
} SceneState; } SceneState;
static const NotificationSequence sequence_short_vibro_and_sound = { static const NotificationSequence notification_sequence_new_token = {
&message_display_backlight_on, &message_display_backlight_on,
&message_green_255, &message_green_255,
&message_vibro_on, &message_vibro_on,
@ -36,6 +38,19 @@ static const NotificationSequence sequence_short_vibro_and_sound = {
NULL, NULL,
}; };
static const NotificationSequence notification_sequence_badusb = {
&message_vibro_on,
&message_note_d5,
&message_delay_50,
&message_note_e4,
&message_delay_50,
&message_note_f3,
&message_delay_50,
&message_vibro_off,
&message_sound_off,
NULL,
};
static void i_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount len) { static void i_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount len) {
uint8_t str_token_length = 0; uint8_t str_token_length = 0;
if(len == TOTP_8_DIGITS) { if(len == TOTP_8_DIGITS) {
@ -137,6 +152,9 @@ void totp_scene_generate_token_activate(
plugin_state->current_scene_state = scene_state; plugin_state->current_scene_state = scene_state;
FURI_LOG_D(LOGGING_TAG, "Timezone set to: %f", (double)plugin_state->timezone_offset); FURI_LOG_D(LOGGING_TAG, "Timezone set to: %f", (double)plugin_state->timezone_offset);
update_totp_params(plugin_state); update_totp_params(plugin_state);
scene_state->hid_worker_context = totp_hid_worker_start();
scene_state->hid_worker_context->string = &scene_state->last_code[0];
scene_state->hid_worker_context->string_length = TOTP_TOKEN_DIGITS_MAX_COUNT + 1;
} }
void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state) { void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state) {
@ -172,12 +190,13 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
scene_state->need_token_update = false; scene_state->need_token_update = false;
scene_state->last_token_gen_time = curr_ts; scene_state->last_token_gen_time = curr_ts;
TokenInfo* tokenInfo = const TokenInfo* tokenInfo =
(TokenInfo*)(list_element_at( (TokenInfo*)(list_element_at(
plugin_state->tokens_list, scene_state->current_token_index) plugin_state->tokens_list, scene_state->current_token_index)
->data); ->data);
if(tokenInfo->token != NULL && tokenInfo->token_length > 0) { if(tokenInfo->token != NULL && tokenInfo->token_length > 0) {
furi_mutex_acquire(scene_state->hid_worker_context->string_sync, FuriWaitForever);
size_t key_length; size_t key_length;
uint8_t* key = totp_crypto_decrypt( uint8_t* key = totp_crypto_decrypt(
tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length); tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
@ -196,11 +215,14 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
memset_s(key, key_length, 0, key_length); memset_s(key, key_length, 0, key_length);
free(key); free(key);
} else { } else {
furi_mutex_acquire(scene_state->hid_worker_context->string_sync, FuriWaitForever);
i_token_to_str(0, scene_state->last_code, tokenInfo->digits); i_token_to_str(0, scene_state->last_code, tokenInfo->digits);
} }
furi_mutex_release(scene_state->hid_worker_context->string_sync);
if(is_new_token_time) { if(is_new_token_time) {
notification_message(plugin_state->notification, &sequence_short_vibro_and_sound); notification_message(plugin_state->notification, &notification_sequence_new_token);
} }
} }
@ -263,11 +285,19 @@ bool totp_scene_generate_token_handle_event(
return false; return false;
} }
SceneState* scene_state;
if(event->input.type == InputTypeLong && event->input.key == InputKeyDown) {
scene_state = (SceneState*)plugin_state->current_scene_state;
totp_hid_worker_notify(scene_state->hid_worker_context, TotpHidWorkerEvtType);
notification_message(plugin_state->notification, &notification_sequence_badusb);
return true;
}
if(event->input.type != InputTypePress) { if(event->input.type != InputTypePress) {
return true; return true;
} }
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; scene_state = (SceneState*)plugin_state->current_scene_state;
switch(event->input.key) { switch(event->input.key) {
case InputKeyUp: case InputKeyUp:
break; break;
@ -312,6 +342,8 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) {
if(plugin_state->current_scene_state == NULL) return; if(plugin_state->current_scene_state == NULL) return;
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
totp_hid_worker_stop(scene_state->hid_worker_context);
free(scene_state); free(scene_state);
plugin_state->current_scene_state = NULL; plugin_state->current_scene_state = NULL;
} }

View file

@ -0,0 +1,106 @@
#include "hid_worker.h"
const uint8_t hid_number_keys[10] = {
HID_KEYBOARD_0,
HID_KEYBOARD_1,
HID_KEYBOARD_2,
HID_KEYBOARD_3,
HID_KEYBOARD_4,
HID_KEYBOARD_5,
HID_KEYBOARD_6,
HID_KEYBOARD_7,
HID_KEYBOARD_8,
HID_KEYBOARD_9};
static void totp_hid_worker_restore_usb_mode(TotpHidWorkerTypeContext* context) {
if(context->usb_mode_prev != NULL) {
furi_hal_usb_set_config(context->usb_mode_prev, NULL);
context->usb_mode_prev = NULL;
}
}
static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
context->usb_mode_prev = furi_hal_usb_get_config();
furi_hal_usb_unlock();
furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true);
uint8_t i = 0;
do {
furi_delay_ms(500);
i++;
} while(!furi_hal_hid_is_connected() && i < 50);
furi_delay_ms(500);
if(furi_hal_hid_is_connected() &&
furi_mutex_acquire(context->string_sync, 500) == FuriStatusOk) {
i = 0;
while(i < context->string_length && context->string[i] != 0) {
uint8_t digit = context->string[i] - '0';
if(digit > 9) break;
uint8_t hid_kb_key = hid_number_keys[digit];
furi_hal_hid_kb_press(hid_kb_key);
furi_delay_ms(30);
furi_hal_hid_kb_release(hid_kb_key);
i++;
}
furi_mutex_release(context->string_sync);
furi_delay_ms(100);
}
totp_hid_worker_restore_usb_mode(context);
}
static int32_t totp_hid_worker_callback(void* context) {
ValueMutex context_mutex;
if(!init_mutex(&context_mutex, context, sizeof(TotpHidWorkerTypeContext))) {
return 251;
}
while(true) {
uint32_t flags = furi_thread_flags_wait(
TotpHidWorkerEvtStop | TotpHidWorkerEvtType, FuriFlagWaitAny, FuriWaitForever);
furi_check((flags & FuriFlagError) == 0); //-V562
if(flags & TotpHidWorkerEvtStop) break;
TotpHidWorkerTypeContext* h_context = acquire_mutex_block(&context_mutex);
if(flags & TotpHidWorkerEvtType) {
totp_hid_worker_type_code(h_context);
}
release_mutex(&context_mutex, h_context);
}
delete_mutex(&context_mutex);
return 0;
}
TotpHidWorkerTypeContext* totp_hid_worker_start() {
TotpHidWorkerTypeContext* context = malloc(sizeof(TotpHidWorkerTypeContext));
furi_check(context != NULL);
context->string_sync = furi_mutex_alloc(FuriMutexTypeNormal);
context->thread = furi_thread_alloc();
context->usb_mode_prev = NULL;
furi_thread_set_name(context->thread, "TOTPHidWorker");
furi_thread_set_stack_size(context->thread, 1024);
furi_thread_set_context(context->thread, context);
furi_thread_set_callback(context->thread, totp_hid_worker_callback);
furi_thread_start(context->thread);
return context;
}
void totp_hid_worker_stop(TotpHidWorkerTypeContext* context) {
furi_assert(context);
furi_thread_flags_set(furi_thread_get_id(context->thread), TotpHidWorkerEvtStop);
furi_thread_join(context->thread);
furi_thread_free(context->thread);
furi_mutex_free(context->string_sync);
totp_hid_worker_restore_usb_mode(context);
free(context);
}
void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event) {
furi_assert(context);
furi_thread_flags_set(furi_thread_get_id(context->thread), event);
}

View file

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

View file

@ -6,6 +6,8 @@ typedef enum { SHA1, SHA256, SHA512 } TokenHashAlgo;
typedef enum { TOTP_6_DIGITS, TOTP_8_DIGITS } TokenDigitsCount; typedef enum { TOTP_6_DIGITS, TOTP_8_DIGITS } TokenDigitsCount;
#define TOTP_TOKEN_DIGITS_MAX_COUNT 8
typedef struct { typedef struct {
uint8_t* token; uint8_t* token;
size_t token_length; size_t token_length;