Skip to content

Commit 8c8a960

Browse files
authored
Implemented export (#219) (#220)
* feat: implemented export (#219) * CLang format changes --------- Co-authored-by: akopachov <akopachov@users.noreply.github.com>
1 parent b42c832 commit 8c8a960

File tree

7 files changed

+153
-4
lines changed

7 files changed

+153
-4
lines changed

app_api_table_i.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <lib/toolbox/args.h>
55
#include <memset_s.h>
66
#include "services/crypto/crypto_facade.h"
7+
#include "types/crypto_settings.h"
78
#include "ui/scene_director.h"
89
#include "services/config/config.h"
910
#include "services/kb_layouts/kb_layout_provider.h"
@@ -74,4 +75,8 @@ static constexpr auto app_api_table = sort(create_array_t<sym_entry>(
7475
API_METHOD(
7576
totp_kb_layout_provider_get_layout_name,
7677
bool,
77-
(AutomationKeyboardLayout, char*, size_t))));
78+
(AutomationKeyboardLayout, char*, size_t)),
79+
API_METHOD(
80+
totp_crypto_decrypt,
81+
uint8_t*,
82+
(const uint8_t*, const size_t, const CryptoSettings*, size_t*))));

application.fam

+8
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,11 @@ App(
164164
requires=["totp"],
165165
sources=["cli/plugins/notification/notification.c", "cli/cli_shared_methods.c"],
166166
)
167+
168+
App(
169+
appid="totp_cli_export_plugin",
170+
apptype=FlipperAppType.PLUGIN,
171+
entry_point="totp_cli_export_plugin_ep",
172+
requires=["totp"],
173+
sources=["cli/plugins/export/export.c", "cli/cli_shared_methods.c"],
174+
)

assets/cli/cli_help.txt

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Usage:
1212
totp (timezone | tz) [<timezone>]
1313
totp reset
1414
totp automation [-k <layout>] [-w <delay>] [<automation>...]
15+
totp export
1516

1617
Commands:
1718
help, h, ? Show command usage help
@@ -27,6 +28,7 @@ Commands:
2728
timezone, tz Get or set current timezone
2829
reset Reset application to default settings
2930
automation Get or set automation settings
31+
export Exports and prints all the tokens into URI-list format
3032

3133
Arguments:
3234
name Token name

cli/cli.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "plugins/automation/meta.h"
1818
#include "plugins/details/meta.h"
1919
#include "plugins/version/meta.h"
20+
#include "plugins/export/meta.h"
2021
#include "cli_plugin_interface.h"
2122
#include "../app_api_interface.h"
2223

@@ -137,6 +138,8 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
137138
external_plugin_name = TOTP_CLI_PLUGIN_DETAILS_FILE_NAME;
138139
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_VERSION) == 0) {
139140
external_plugin_name = TOTP_CLI_PLUGIN_VERSION_FILE_NAME;
141+
} else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_EXPORT) == 0) {
142+
external_plugin_name = TOTP_CLI_PLUGIN_EXPORT_FILE_NAME;
140143
} else {
141144
totp_cli_print_unknown_command(cmd);
142145
}
@@ -172,4 +175,4 @@ void totp_cli_unregister_command_handler(TotpCliContext* context) {
172175

173176
furi_record_close(RECORD_CLI);
174177
free(context);
175-
}
178+
}

cli/plugins/export/export.c

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#include <lib/toolbox/args.h>
2+
#include <flipper_application/flipper_application.h>
3+
#include "../../../lib/polyfills/memset_s.h"
4+
#include "../../../services/config/config.h"
5+
#include "../../../services/crypto/crypto_facade.h"
6+
#include "../../../ui/scene_director.h"
7+
#include "../../cli_helpers.h"
8+
#include "../../cli_plugin_interface.h"
9+
#include "../../cli_shared_methods.h"
10+
11+
static const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
12+
13+
static void print_as_base32(const uint8_t* data, size_t length) {
14+
int buffer = data[0];
15+
size_t next = 1;
16+
int bitsLeft = 8;
17+
while(bitsLeft > 0 || next < length) {
18+
if(bitsLeft < 5) {
19+
if(next < length) {
20+
buffer <<= 8;
21+
buffer |= data[next++] & 0xFF;
22+
bitsLeft += 8;
23+
} else {
24+
int pad = 5 - bitsLeft;
25+
buffer <<= pad;
26+
bitsLeft += pad; //-V1026
27+
}
28+
}
29+
int index = 0x1F & (buffer >> (bitsLeft - 5));
30+
bitsLeft -= 5;
31+
putchar(BASE32_ALPHABET[index]);
32+
}
33+
}
34+
35+
static void print_uri_component(const char* data, size_t length) {
36+
const char* c_ptr = data;
37+
const char* last_ptr = data + length;
38+
while(c_ptr < last_ptr) {
39+
const char c = *c_ptr;
40+
if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
41+
c == '-' || c == '_') {
42+
putchar(c);
43+
} else {
44+
printf("%%%x", c);
45+
}
46+
c_ptr++;
47+
}
48+
}
49+
50+
static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
51+
UNUSED(args);
52+
UNUSED(plugin_state);
53+
if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
54+
return;
55+
}
56+
57+
TOTP_CLI_PRINTF_WARNING("WARNING!\r\n");
58+
TOTP_CLI_PRINTF_WARNING(
59+
"ALL THE INFORMATION (INCL. UNENCRYPTED SECRET) ABOUT ALL THE TOKENS WILL BE EXPORTED AND PRINTED TO THE CONSOLE.\r\n");
60+
TOTP_CLI_PRINTF_WARNING("Confirm? [y/n]\r\n");
61+
fflush(stdout);
62+
char user_pick;
63+
do {
64+
user_pick = tolower(cli_getc(cli));
65+
} while(user_pick != 'y' && user_pick != 'n' && user_pick != CliSymbolAsciiCR &&
66+
user_pick != CliSymbolAsciiETX && user_pick != CliSymbolAsciiEsc);
67+
68+
if(user_pick != 'y' && user_pick != CliSymbolAsciiCR) {
69+
TOTP_CLI_PRINTF_INFO("User has not confirmed\r\n");
70+
return;
71+
}
72+
73+
TokenInfoIteratorContext* iterator_context =
74+
totp_config_get_token_iterator_context(plugin_state);
75+
size_t total_count = totp_token_info_iterator_get_total_count(iterator_context);
76+
77+
TOTP_CLI_LOCK_UI(plugin_state);
78+
79+
size_t original_index = totp_token_info_iterator_get_current_token_index(iterator_context);
80+
81+
cli_nl();
82+
TOTP_CLI_PRINTF("# --- EXPORT LIST BEGIN ---\r\n");
83+
84+
for(size_t i = 0; i < total_count; i++) {
85+
totp_token_info_iterator_go_to(iterator_context, i);
86+
const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context);
87+
TOTP_CLI_PRINTF("otpauth://%s/", token_info_get_type_as_cstr(token_info));
88+
print_uri_component(
89+
furi_string_get_cstr(token_info->name), furi_string_size(token_info->name));
90+
TOTP_CLI_PRINTF("?secret=");
91+
size_t key_length;
92+
uint8_t* key = totp_crypto_decrypt(
93+
token_info->token,
94+
token_info->token_length,
95+
&plugin_state->crypto_settings,
96+
&key_length);
97+
print_as_base32(key, key_length);
98+
memset_s(key, key_length, 0, key_length);
99+
free(key);
100+
TOTP_CLI_PRINTF("&algorithm=%s", token_info_get_algo_as_cstr(token_info));
101+
TOTP_CLI_PRINTF("&digits=%" PRIu8, token_info->digits);
102+
if(token_info->type == TokenTypeHOTP) {
103+
TOTP_CLI_PRINTF("&counter=%" PRIu64, token_info->counter);
104+
} else {
105+
TOTP_CLI_PRINTF("&period=%" PRIu8, token_info->duration);
106+
}
107+
cli_nl();
108+
}
109+
110+
TOTP_CLI_PRINTF("# --- EXPORT LIST END ---\r\n\r\n");
111+
112+
totp_token_info_iterator_go_to(iterator_context, original_index);
113+
114+
TOTP_CLI_UNLOCK_UI(plugin_state);
115+
}
116+
117+
static const CliPlugin plugin = {.name = "TOTP CLI Plugin: Export", .handle = &handle};
118+
119+
static const FlipperAppPluginDescriptor plugin_descriptor = {
120+
.appid = PLUGIN_APP_ID,
121+
.ep_api_version = PLUGIN_API_VERSION,
122+
.entry_point = &plugin,
123+
};
124+
125+
const FlipperAppPluginDescriptor* totp_cli_export_plugin_ep() {
126+
return &plugin_descriptor;
127+
}

cli/plugins/export/meta.h

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
3+
#define TOTP_CLI_COMMAND_EXPORT "export"
4+
#define TOTP_CLI_PLUGIN_EXPORT_FILE_NAME "totp_cli_export_plugin"

cli/plugins/list/list.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static void handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
3939
totp_config_get_token_iterator_context(plugin_state);
4040
size_t total_count = totp_token_info_iterator_get_total_count(iterator_context);
4141
if(total_count <= 0) {
42-
TOTP_CLI_PRINTF("There are no tokens");
42+
TOTP_CLI_PRINTF("There are no tokens\r\n");
4343
return;
4444
}
4545

@@ -79,4 +79,4 @@ static const FlipperAppPluginDescriptor plugin_descriptor = {
7979

8080
const FlipperAppPluginDescriptor* totp_cli_list_plugin_ep() {
8181
return &plugin_descriptor;
82-
}
82+
}

0 commit comments

Comments
 (0)