Skip to content

Commit 3641ebf

Browse files
committed
* Made PIN optional (#4)
* Few refactoring
1 parent a8a49df commit 3641ebf

File tree

10 files changed

+140
-62
lines changed

10 files changed

+140
-62
lines changed

totp/scenes/authenticate/totp_scene_authenticate.c

+3-37
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
#include "../../services/config/config.h"
77
#include "../scene_director.h"
88
#include "../totp_scenes_enum.h"
9+
#include "../../services/crypto/crypto.h"
910

1011
#define MAX_CODE_LENGTH TOTP_IV_SIZE
11-
#define CRYPTO_VERIFY_KEY "FFF_Crypto_pass"
12-
#define CRYPTO_VERIFY_KEY_LENGTH 16
1312

1413
typedef struct {
1514
uint8_t code_input[MAX_CODE_LENGTH];
@@ -93,42 +92,9 @@ bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState*
9392
}
9493
break;
9594
case InputKeyOk:
96-
if (plugin_state->crypto_verify_data == NULL) {
97-
FURI_LOG_D(LOGGING_TAG, "Generating new IV");
98-
furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE);
99-
}
100-
101-
memcpy(&plugin_state->iv[0], &plugin_state->base_iv[0], TOTP_IV_SIZE);
102-
for (uint8_t i = 0; i < scene_state->code_length; i++) {
103-
plugin_state->iv[i] = plugin_state->iv[i] ^ (uint8_t)(scene_state->code_input[i] * (i + 1));
104-
}
105-
106-
if (plugin_state->crypto_verify_data == NULL) {
107-
FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data");
108-
plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
109-
plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH;
110-
Storage* storage = totp_open_storage();
111-
FlipperFormat* config_file = totp_open_config_file(storage);
112-
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, &plugin_state->iv[0]);
113-
furi_hal_crypto_encrypt((uint8_t* )CRYPTO_VERIFY_KEY, plugin_state->crypto_verify_data, CRYPTO_VERIFY_KEY_LENGTH);
114-
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
115-
flipper_format_insert_or_update_hex(config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE);
116-
flipper_format_insert_or_update_hex(config_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, plugin_state->crypto_verify_data, CRYPTO_VERIFY_KEY_LENGTH);
117-
totp_close_config_file(config_file);
118-
totp_close_storage();
119-
}
120-
121-
uint8_t decrypted_key[CRYPTO_VERIFY_KEY_LENGTH];
122-
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, &plugin_state->iv[0]);
123-
furi_hal_crypto_decrypt(plugin_state->crypto_verify_data, &decrypted_key[0], CRYPTO_VERIFY_KEY_LENGTH);
124-
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
125-
126-
bool key_valid = true;
127-
for (uint8_t i = 0; i < CRYPTO_VERIFY_KEY_LENGTH && key_valid; i++) {
128-
if (decrypted_key[i] != CRYPTO_VERIFY_KEY[i]) key_valid = false;
129-
}
95+
totp_crypto_seed_iv(plugin_state, &scene_state->code_input[0], scene_state->code_length);
13096

131-
if (key_valid) {
97+
if (totp_crypto_verify_key(plugin_state)) {
13298
FURI_LOG_D(LOGGING_TAG, "PIN is valid");
13399
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
134100
} else {

totp/scenes/generate_token/totp_scene_generate_token.c

+5-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "../../services/ui/constants.h"
99
#include "../../services/totp/totp.h"
1010
#include "../../services/config/config.h"
11+
#include "../../services/crypto/crypto.h"
1112
#include "../scene_director.h"
1213
#include "../token_menu/totp_scene_token_menu.h"
1314

@@ -133,14 +134,11 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
133134

134135
TokenInfo* tokenInfo = (TokenInfo*)(list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data);
135136

136-
uint8_t* key = malloc(tokenInfo->token_length);
137+
uint8_t key_length;
138+
uint8_t* key = totp_crypto_decrypt(tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
137139

138-
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, &plugin_state->iv[0]);
139-
furi_hal_crypto_decrypt(tokenInfo->token, key, tokenInfo->token_length);
140-
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
141-
142-
i_token_to_str(totp_at(get_totp_algo_impl(tokenInfo->algo), token_info_get_digits_count(tokenInfo), key, tokenInfo->token_length, curr_ts, plugin_state->timezone_offset, TOKEN_LIFETIME), scene_state->last_code, tokenInfo->digits);
143-
memset(key, 0, tokenInfo->token_length);
140+
i_token_to_str(totp_at(get_totp_algo_impl(tokenInfo->algo), token_info_get_digits_count(tokenInfo), key, key_length, curr_ts, plugin_state->timezone_offset, TOKEN_LIFETIME), scene_state->last_code, tokenInfo->digits);
141+
memset(key, 0, key_length);
144142
free(key);
145143

146144
if (is_new_token_time) {

totp/services/config/config.c

+7
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ void totp_full_save_config_file(PluginState* const plugin_state) {
167167
flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE);
168168
flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length);
169169
flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1);
170+
flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1);
170171
ListNode* node = plugin_state->tokens_list;
171172
while (node != NULL) {
172173
TokenInfo* token_info = node->data;
@@ -247,6 +248,12 @@ void totp_config_file_load_base(PluginState* const plugin_state) {
247248
FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0");
248249
}
249250

251+
flipper_format_rewind(fff_data_file);
252+
253+
if (!flipper_format_read_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
254+
plugin_state->pin_set = true;
255+
}
256+
250257
furi_string_free(temp_str);
251258
totp_close_config_file(fff_data_file);
252259
totp_close_storage();

totp/services/config/constants.h

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define TOTP_CONFIG_KEY_TOKEN_DIGITS "TokenDigits"
1111
#define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto"
1212
#define TOTP_CONFIG_KEY_BASE_IV "BaseIV"
13+
#define TOTP_CONFIG_KEY_PINSET "PinIsSet"
1314

1415
#define TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME "sha1"
1516
#define TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME "sha256"

totp/services/crypto/crypto.c

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include "crypto.h"
2+
#include <furi.h>
3+
#include <furi_hal.h>
4+
#include "../config/config.h"
5+
#include "../../types/common.h"
6+
7+
#define CRYPTO_KEY_SLOT 2
8+
#define CRYPTO_VERIFY_KEY "FFF_Crypto_pass"
9+
#define CRYPTO_VERIFY_KEY_LENGTH 16
10+
#define CRYPTO_ALIGNMENT_FACTOR 16
11+
12+
uint8_t* totp_crypto_encrypt(const uint8_t* plain_data, const uint8_t plain_data_length, const uint8_t* iv, uint8_t* encrypted_data_length) {
13+
uint8_t* encrypted_data;
14+
size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR;
15+
if(remain) {
16+
uint8_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR;
17+
uint8_t* plain_data_aligned = malloc(plain_data_aligned_length);
18+
memset(plain_data_aligned, 0, plain_data_aligned_length);
19+
memcpy(plain_data_aligned, plain_data, plain_data_length);
20+
21+
encrypted_data = malloc(plain_data_aligned_length);
22+
*encrypted_data_length = plain_data_aligned_length;
23+
24+
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
25+
furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length);
26+
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
27+
28+
memset(plain_data_aligned, 0, plain_data_aligned_length);
29+
free(plain_data_aligned);
30+
} else {
31+
encrypted_data = malloc(plain_data_length);
32+
*encrypted_data_length = plain_data_length;
33+
34+
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
35+
furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length);
36+
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
37+
}
38+
39+
return encrypted_data;
40+
}
41+
42+
uint8_t* totp_crypto_decrypt(const uint8_t* encrypted_data, const uint8_t encrypted_data_length, const uint8_t* iv, uint8_t* decrypted_data_length) {
43+
*decrypted_data_length = encrypted_data_length;
44+
uint8_t* decrypted_data = malloc(*decrypted_data_length);
45+
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
46+
furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length);
47+
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
48+
return decrypted_data;
49+
}
50+
51+
void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length) {
52+
if (plugin_state->crypto_verify_data == NULL) {
53+
FURI_LOG_D(LOGGING_TAG, "Generating new IV");
54+
furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE);
55+
}
56+
57+
memcpy(&plugin_state->iv[0], &plugin_state->base_iv[0], TOTP_IV_SIZE);
58+
if (pin != NULL && pin_length > 0) {
59+
for (uint8_t i = 0; i < pin_length; i++) {
60+
plugin_state->iv[i] = plugin_state->iv[i] ^ (uint8_t)(pin[i] * (i + 1));
61+
}
62+
}
63+
64+
if (plugin_state->crypto_verify_data == NULL) {
65+
FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data");
66+
plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
67+
plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH;
68+
Storage* storage = totp_open_storage();
69+
FlipperFormat* config_file = totp_open_config_file(storage);
70+
71+
plugin_state->crypto_verify_data = totp_crypto_encrypt((uint8_t* )CRYPTO_VERIFY_KEY, CRYPTO_VERIFY_KEY_LENGTH, &plugin_state->iv[0], &plugin_state->crypto_verify_data_length);
72+
73+
flipper_format_insert_or_update_hex(config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE);
74+
flipper_format_insert_or_update_hex(config_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, plugin_state->crypto_verify_data, CRYPTO_VERIFY_KEY_LENGTH);
75+
plugin_state->pin_set = pin != NULL && pin_length > 0;
76+
flipper_format_insert_or_update_bool(config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1);
77+
totp_close_config_file(config_file);
78+
totp_close_storage();
79+
}
80+
}
81+
82+
bool totp_crypto_verify_key(const PluginState* plugin_state) {
83+
uint8_t decrypted_key_length;
84+
uint8_t* decrypted_key = totp_crypto_decrypt(plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length, &plugin_state->iv[0], &decrypted_key_length);
85+
86+
bool key_valid = true;
87+
for (uint8_t i = 0; i < CRYPTO_VERIFY_KEY_LENGTH && key_valid; i++) {
88+
if (decrypted_key[i] != CRYPTO_VERIFY_KEY[i]) key_valid = false;
89+
}
90+
91+
return key_valid;
92+
}

totp/services/crypto/crypto.h

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#include "../../types/plugin_state.h"
4+
5+
uint8_t* totp_crypto_encrypt(const uint8_t* plain_data, const uint8_t plain_data_length, const uint8_t* iv, uint8_t* encrypted_data_length);
6+
uint8_t* totp_crypto_decrypt(const uint8_t* encrypted_data, const uint8_t encrypted_data_length, const uint8_t* iv, uint8_t* decrypted_data_length);
7+
void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length);
8+
bool totp_crypto_verify_key(const PluginState* plugin_state);

totp/totp_app.c

+21-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "types/event_type.h"
1717
#include "types/common.h"
1818
#include "scenes/scene_director.h"
19+
#include "services/ui/constants.h"
20+
#include "services/crypto/crypto.h"
1921

2022
#define IDLE_TIMEOUT 60000
2123

@@ -42,7 +44,25 @@ static void totp_state_init(PluginState* const plugin_state) {
4244
totp_config_file_load_base(plugin_state);
4345

4446
totp_scene_director_init_scenes(plugin_state);
45-
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
47+
48+
if (plugin_state->crypto_verify_data == NULL) {
49+
DialogMessage* message = dialog_message_alloc();
50+
dialog_message_set_buttons(message, "No", NULL, "Yes");
51+
dialog_message_set_text(message, "Would you like to setup PIN?", SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter);
52+
DialogMessageButton dialog_result = dialog_message_show(plugin_state->dialogs, message);
53+
dialog_message_free(message);
54+
if (dialog_result == DialogMessageButtonRight) {
55+
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
56+
} else {
57+
totp_crypto_seed_iv(plugin_state, NULL, 0);
58+
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
59+
}
60+
} else if (plugin_state->pin_set) {
61+
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
62+
} else {
63+
totp_crypto_seed_iv(plugin_state, NULL, 0);
64+
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
65+
}
4666
}
4767

4868
static void dispose_plugin_state(PluginState* plugin_state) {

totp/types/common.h

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
#pragma once
22

33
#define LOGGING_TAG "TOTP APP"
4-
#define CRYPTO_KEY_SLOT 2

totp/types/plugin_state.h

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ typedef struct {
2323

2424
uint8_t* crypto_verify_data;
2525
uint8_t crypto_verify_data_length;
26+
bool pin_set;
2627
uint8_t iv[TOTP_IV_SIZE];
2728
uint8_t base_iv[TOTP_IV_SIZE];
2829
} PluginState;

totp/types/token_info.c

+2-16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "stdlib.h"
55
#include "common.h"
66
#include "../services/base32/base32.h"
7+
#include "../services/crypto/crypto.h"
78

89
TokenInfo* token_info_alloc() {
910
TokenInfo* tokenInfo = malloc(sizeof(TokenInfo));
@@ -22,23 +23,8 @@ void token_info_free(TokenInfo* token_info) {
2223
void token_info_set_secret(TokenInfo* token_info, const char* base32_token_secret, uint8_t token_secret_length, uint8_t* iv) {
2324
uint8_t* plain_secret = malloc(token_secret_length);
2425
int plain_secret_length = base32_decode((uint8_t *)base32_token_secret, plain_secret, token_secret_length);
25-
token_info->token_length = plain_secret_length;
2626

27-
size_t remain = token_info->token_length % 16;
28-
if(remain) {
29-
token_info->token_length = token_info->token_length - remain + 16;
30-
uint8_t* plain_secret_aligned = malloc(token_info->token_length);
31-
memcpy(plain_secret_aligned, plain_secret, plain_secret_length);
32-
memset(plain_secret, 0, plain_secret_length);
33-
free(plain_secret);
34-
plain_secret = plain_secret_aligned;
35-
}
36-
37-
token_info->token = malloc(token_info->token_length);
38-
39-
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
40-
furi_hal_crypto_encrypt(plain_secret, token_info->token, token_info->token_length);
41-
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
27+
token_info->token = totp_crypto_encrypt(plain_secret, plain_secret_length, iv, &token_info->token_length);
4228

4329
memset(plain_secret, 0, token_info->token_length);
4430
free(plain_secret);

0 commit comments

Comments
 (0)