Skip to content

Commit 766a3d6

Browse files
authored
Implemented "type code in badusb mode"
* Implemented #21
1 parent 3a111ef commit 766a3d6

File tree

4 files changed

+161
-5
lines changed

4 files changed

+161
-5
lines changed

scenes/generate_token/totp_scene_generate_token.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@
1313
#include "../../services/roll_value/roll_value.h"
1414
#include "../scene_director.h"
1515
#include "../token_menu/totp_scene_token_menu.h"
16+
#include "../../services/hid_worker/hid_worker.h"
1617

1718
#define TOKEN_LIFETIME 30
1819
#define DIGIT_TO_CHAR(digit) ((digit) + '0')
1920

2021
typedef struct {
2122
uint16_t current_token_index;
22-
char last_code[9];
23+
char last_code[TOTP_TOKEN_DIGITS_MAX_COUNT + 1];
2324
char* last_code_name;
2425
bool need_token_update;
2526
uint32_t last_token_gen_time;
27+
TotpHidWorkerTypeContext* hid_worker_context;
2628
} SceneState;
2729

28-
static const NotificationSequence sequence_short_vibro_and_sound = {
30+
static const NotificationSequence notification_sequence_new_token = {
2931
&message_display_backlight_on,
3032
&message_green_255,
3133
&message_vibro_on,
@@ -36,6 +38,19 @@ static const NotificationSequence sequence_short_vibro_and_sound = {
3638
NULL,
3739
};
3840

41+
static const NotificationSequence notification_sequence_badusb = {
42+
&message_vibro_on,
43+
&message_note_d5,
44+
&message_delay_50,
45+
&message_note_e4,
46+
&message_delay_50,
47+
&message_note_f3,
48+
&message_delay_50,
49+
&message_vibro_off,
50+
&message_sound_off,
51+
NULL,
52+
};
53+
3954
static void i_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount len) {
4055
uint8_t str_token_length = 0;
4156
if(len == TOTP_8_DIGITS) {
@@ -137,6 +152,9 @@ void totp_scene_generate_token_activate(
137152
plugin_state->current_scene_state = scene_state;
138153
FURI_LOG_D(LOGGING_TAG, "Timezone set to: %f", (double)plugin_state->timezone_offset);
139154
update_totp_params(plugin_state);
155+
scene_state->hid_worker_context = totp_hid_worker_start();
156+
scene_state->hid_worker_context->string = &scene_state->last_code[0];
157+
scene_state->hid_worker_context->string_length = TOTP_TOKEN_DIGITS_MAX_COUNT + 1;
140158
}
141159

142160
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_
172190
scene_state->need_token_update = false;
173191
scene_state->last_token_gen_time = curr_ts;
174192

175-
TokenInfo* tokenInfo =
193+
const TokenInfo* tokenInfo =
176194
(TokenInfo*)(list_element_at(
177195
plugin_state->tokens_list, scene_state->current_token_index)
178196
->data);
179197

180198
if(tokenInfo->token != NULL && tokenInfo->token_length > 0) {
199+
furi_mutex_acquire(scene_state->hid_worker_context->string_sync, FuriWaitForever);
181200
size_t key_length;
182201
uint8_t* key = totp_crypto_decrypt(
183202
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_
196215
memset_s(key, key_length, 0, key_length);
197216
free(key);
198217
} else {
218+
furi_mutex_acquire(scene_state->hid_worker_context->string_sync, FuriWaitForever);
199219
i_token_to_str(0, scene_state->last_code, tokenInfo->digits);
200220
}
201221

222+
furi_mutex_release(scene_state->hid_worker_context->string_sync);
223+
202224
if(is_new_token_time) {
203-
notification_message(plugin_state->notification, &sequence_short_vibro_and_sound);
225+
notification_message(plugin_state->notification, &notification_sequence_new_token);
204226
}
205227
}
206228

@@ -263,11 +285,19 @@ bool totp_scene_generate_token_handle_event(
263285
return false;
264286
}
265287

288+
SceneState* scene_state;
289+
if(event->input.type == InputTypeLong && event->input.key == InputKeyDown) {
290+
scene_state = (SceneState*)plugin_state->current_scene_state;
291+
totp_hid_worker_notify(scene_state->hid_worker_context, TotpHidWorkerEvtType);
292+
notification_message(plugin_state->notification, &notification_sequence_badusb);
293+
return true;
294+
}
295+
266296
if(event->input.type != InputTypePress) {
267297
return true;
268298
}
269299

270-
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
300+
scene_state = (SceneState*)plugin_state->current_scene_state;
271301
switch(event->input.key) {
272302
case InputKeyUp:
273303
break;
@@ -312,6 +342,8 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) {
312342
if(plugin_state->current_scene_state == NULL) return;
313343
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
314344

345+
totp_hid_worker_stop(scene_state->hid_worker_context);
346+
315347
free(scene_state);
316348
plugin_state->current_scene_state = NULL;
317349
}

services/hid_worker/hid_worker.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#include "hid_worker.h"
2+
3+
const uint8_t hid_number_keys[10] = {
4+
HID_KEYBOARD_0,
5+
HID_KEYBOARD_1,
6+
HID_KEYBOARD_2,
7+
HID_KEYBOARD_3,
8+
HID_KEYBOARD_4,
9+
HID_KEYBOARD_5,
10+
HID_KEYBOARD_6,
11+
HID_KEYBOARD_7,
12+
HID_KEYBOARD_8,
13+
HID_KEYBOARD_9};
14+
15+
static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
16+
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
17+
furi_hal_usb_unlock();
18+
furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true);
19+
uint8_t i = 0;
20+
do {
21+
furi_delay_ms(500);
22+
i++;
23+
} while(!furi_hal_hid_is_connected() && i < 100);
24+
25+
if(furi_hal_hid_is_connected() &&
26+
furi_mutex_acquire(context->string_sync, 500) == FuriStatusOk) {
27+
i = 0;
28+
while(i < context->string_length && context->string[i] != 0) {
29+
uint8_t digit = context->string[i] - '0';
30+
if(digit > 9) break;
31+
uint8_t hid_kb_key = hid_number_keys[digit];
32+
furi_hal_hid_kb_press(hid_kb_key);
33+
furi_delay_ms(30);
34+
furi_hal_hid_kb_release(hid_kb_key);
35+
i++;
36+
}
37+
38+
furi_mutex_release(context->string_sync);
39+
40+
furi_hal_hid_kb_press(HID_KEYBOARD_RETURN);
41+
furi_delay_ms(30);
42+
furi_hal_hid_kb_release(HID_KEYBOARD_RETURN);
43+
44+
furi_delay_ms(100);
45+
}
46+
47+
furi_hal_usb_set_config(usb_mode_prev, NULL);
48+
}
49+
50+
static int32_t totp_hid_worker_callback(void* context) {
51+
ValueMutex context_mutex;
52+
if(!init_mutex(&context_mutex, context, sizeof(TotpHidWorkerTypeContext))) {
53+
return 251;
54+
}
55+
56+
while(true) {
57+
uint32_t flags = furi_thread_flags_wait(
58+
TotpHidWorkerEvtStop | TotpHidWorkerEvtType, FuriFlagWaitAny, FuriWaitForever);
59+
furi_check((flags & FuriFlagError) == 0); //-V562
60+
if(flags & TotpHidWorkerEvtStop) break;
61+
62+
TotpHidWorkerTypeContext* h_context = acquire_mutex_block(&context_mutex);
63+
if(flags & TotpHidWorkerEvtType) {
64+
totp_hid_worker_type_code(h_context);
65+
}
66+
67+
release_mutex(&context_mutex, h_context);
68+
}
69+
70+
delete_mutex(&context_mutex);
71+
72+
return 0;
73+
}
74+
75+
TotpHidWorkerTypeContext* totp_hid_worker_start() {
76+
TotpHidWorkerTypeContext* context = malloc(sizeof(TotpHidWorkerTypeContext));
77+
furi_check(context != NULL);
78+
context->string_sync = furi_mutex_alloc(FuriMutexTypeNormal);
79+
context->thread = furi_thread_alloc();
80+
furi_thread_set_name(context->thread, "TOTPHidWorker");
81+
furi_thread_set_stack_size(context->thread, 1024);
82+
furi_thread_set_context(context->thread, context);
83+
furi_thread_set_callback(context->thread, totp_hid_worker_callback);
84+
furi_thread_start(context->thread);
85+
return context;
86+
}
87+
88+
void totp_hid_worker_stop(TotpHidWorkerTypeContext* context) {
89+
furi_assert(context);
90+
furi_thread_flags_set(furi_thread_get_id(context->thread), TotpHidWorkerEvtStop);
91+
furi_thread_join(context->thread);
92+
furi_thread_free(context->thread);
93+
furi_mutex_free(context->string_sync);
94+
free(context);
95+
}
96+
97+
void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event) {
98+
furi_assert(context);
99+
furi_thread_flags_set(furi_thread_get_id(context->thread), event);
100+
}

services/hid_worker/hid_worker.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include <stdlib.h>
4+
#include <furi/furi.h>
5+
#include <furi_hal.h>
6+
7+
typedef struct {
8+
char* string;
9+
uint8_t string_length;
10+
FuriThread* thread;
11+
FuriMutex* string_sync;
12+
} TotpHidWorkerTypeContext;
13+
14+
typedef enum {
15+
TotpHidWorkerEvtReserved = (1 << 0),
16+
TotpHidWorkerEvtStop = (1 << 1),
17+
TotpHidWorkerEvtType = (1 << 2)
18+
} TotpHidWorkerEvtFlags;
19+
20+
TotpHidWorkerTypeContext* totp_hid_worker_start();
21+
void totp_hid_worker_stop(TotpHidWorkerTypeContext* context);
22+
void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event);

types/token_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ typedef enum { SHA1, SHA256, SHA512 } TokenHashAlgo;
66

77
typedef enum { TOTP_6_DIGITS, TOTP_8_DIGITS } TokenDigitsCount;
88

9+
#define TOTP_TOKEN_DIGITS_MAX_COUNT 8
10+
911
typedef struct {
1012
uint8_t* token;
1113
size_t token_length;

0 commit comments

Comments
 (0)