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+ }
0 commit comments