This commit is contained in:
VerstreuteSeele
2022-12-21 23:20:39 +01:00
26 changed files with 748 additions and 423 deletions
+2 -2
View File
@@ -61,7 +61,7 @@ PVS-Studio.log
.gdbinit
PATREONbuildRelease.sh
RM*-*.tgz
RM*-*.zip
RM*-*-*/
RM*-*-*/
PATREONbuildRelease.sh
+7 -1
View File
@@ -16,7 +16,13 @@ ___________________________________________________________________________
В настройках задается минимальный размер нагрузки (payload)<br>
После принятия, пакет сдвигается побитно и валидируется. Побитный сдвиг сильно увеличивает вероятность отлова пакета, но так же увеличивается количество мусорных пакетов.<br>
Количество уникальных адресов запоминается (просмотр - стрелка вниз в режиме просмотра адресов)<br>
После поиска можно переключиться в режим сканирования по найденным адресам или сканировать адрес конкретного пакета - нажать ОК в режиме просмотра адресов<br>
После поиска можно переключиться в режим сканирования по найденным адресам или сканировать адрес конкретного пакета или группы адресов с различным LSB в адресе<br>
<br>
<img src="https://raw.githubusercontent.com/vad7/nrf24scan/master/Screenshot-6.png">
<br>
Адреса, которые попались дважды и более раз отображаются списком:<br>
<img src="https://raw.githubusercontent.com/vad7/nrf24scan/master/Screenshot-7.png">
<br><br>
Изменение режима sniff/scan - стрелками на пункте Scan.<br><br>
Режим сканирования (scan) - просто чтение пакетов по заданным в настройках мак адресам и виду пакета - ESB/DPL.<br>
На начальном экране в режиме чтения можно загрузить файл настроек (по умолчанию загружается settings.txt из папки nrf24_scanner на SD карте).<br>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

+125 -161
View File
@@ -14,11 +14,11 @@
#include <u8g2.h>
#define TAG "nrf24scan"
#define VERSION "2.0"
#define VERSION "2.1"
#define MAX_CHANNEL 125
#define MAX_ADDR 6
#define SCAN_APP_PATH_FOLDER "/ext/apps_data/nrf24scan"
#define SCAN_APP_PATH_FOLDER "/ext/nrf24scan"
#define SETTINGS_FILENAME "addresses.txt" // Settings file format (1 parameter per line):
// SNIFF - if present then sniff mode
// Rate: 0/1/2 - rate in Mbps (=0.25/1/2)
@@ -41,7 +41,7 @@
#define LOG_FILENAME "log"
#define LOG_FILEEXT ".txt"
#define MAX_LOG_RECORDS 200
#define MAX_FOUND_RECORDS 100
#define MAX_FOUND_RECORDS 70
#define LOG_REC_SIZE 34 // max packet size
#define VIEW_LOG_MAX_X 22
#define VIEW_LOG_WIDTH_B 10 // bytes
@@ -87,7 +87,7 @@ struct ADDRS addrs;
struct ADDRS addrs_sniff;
bool sniff_loaded = 0;
int16_t found_total;
int16_t view_found = -1;
int16_t view_found;
int8_t log_to_file = 0; // 0 - no, 1 - yes(new), 2 - append, -1 - only clear
uint16_t log_arr_idx;
@@ -165,7 +165,7 @@ void clear_log() {
view_log_arr_idx = 0;
last_packet_send = -1;
found_total = 0;
view_found = 0;
view_found = -1;
}
void write_to_log_file(Storage* storage, bool f_settings) {
@@ -455,6 +455,28 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu
furi_message_queue_put(event_queue, &event, FuriWaitForever);
}
void check_add_addr(uint8_t* pkt) {
if(addrs.addr_count > 0 && memcmp(addrs.addr_P0, pkt, addrs.addr_len) == 0) return;
if(addrs.addr_count > 1 && memcmp(addrs.addr_P1, pkt, addrs.addr_len - 1) == 0) {
if(addrs.addr_P1[addrs.addr_len - 1] == pkt[addrs.addr_len - 1]) return;
if(addrs.addr_count > 2 && addrs.addr_P2 == pkt[addrs.addr_len - 1]) return;
if(addrs.addr_count > 3 && addrs.addr_P3 == pkt[addrs.addr_len - 1]) return;
if(addrs.addr_count > 4 && addrs.addr_P4 == pkt[addrs.addr_len - 1]) return;
if(addrs.addr_count > 5 && addrs.addr_P5 == pkt[addrs.addr_len - 1]) return;
}
if(addrs.addr_count == 1)
memcpy(addrs.addr_P1, pkt, addrs.addr_len);
else if(addrs.addr_count == 2)
addrs.addr_P2 = pkt[addrs.addr_len - 1];
else if(addrs.addr_count == 3)
addrs.addr_P3 = pkt[addrs.addr_len - 1];
else if(addrs.addr_count == 4)
addrs.addr_P4 = pkt[addrs.addr_len - 1];
else if(addrs.addr_count == 5)
addrs.addr_P5 = pkt[addrs.addr_len - 1];
addrs.addr_count++;
}
static void prepare_nrf24(bool fsend_packet) {
nrf24_write_reg(nrf24_HANDLE, REG_STATUS, 0x70); // clear interrupts
nrf24_write_reg(nrf24_HANDLE, REG_RF_SETUP, NRF_rate);
@@ -462,11 +484,32 @@ static void prepare_nrf24(bool fsend_packet) {
struct ADDRS* adr = what_to_do == 1 ? &addrs_sniff : &addrs;
if(!fsend_packet) {
uint8_t payload = NRF_Payload;
uint8_t* rec = APP->log_arr + view_log_arr_idx * LOG_REC_SIZE;
uint8_t addr_size = (*(rec + 1) & 0b11) + 2;
bool setup_from_log = false;
if(what_to_do >= 2) {
if(log_arr_idx && (*rec & 0x80)) {
setup_from_log = true;
memcpy(addrs.addr_P0, rec + 2, addr_size);
addrs.addr_count = 1;
addrs.addr_len = addr_size;
payload = *(rec + 1) >> 3;
if(what_to_do == 2) {
uint8_t* p = APP->log_arr + 2;
int16_t i = 0;
for(i = 0; i < log_arr_idx; i++, p += LOG_REC_SIZE) {
if((*(p - 2) & 0x80) && (*(p - 1) & 0b11) + 2 == addr_size &&
rec + 2 != p) {
if(memcmp(p, addrs.addr_P0, addr_size - 1) == 0) {
check_add_addr(rec + 2);
if(addrs.addr_count >= 6) break;
}
}
}
}
}
}
if(what_to_do == 1) { // SNIFF
if(adr->addr_count == 0) return;
//payload += 5 + NRF_CRC; // + addr_max + CRC
//if(NRF_ESB) payload += 2;
//if(payload > 32) payload = 32;
payload = 32;
nrf24_write_reg(nrf24_HANDLE, REG_CONFIG, 0x70); // Mask all interrupts
nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, 0); // Automatic Retransmission
@@ -475,8 +518,28 @@ static void prepare_nrf24(bool fsend_packet) {
nrf24_HANDLE,
REG_FEATURE,
0); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload
} else if(what_to_do == 2) {
if(adr->addr_count == 0) return;
} else if(setup_from_log) { // Scan
nrf24_write_reg(
nrf24_HANDLE,
REG_CONFIG,
0x70 | ((NRF_CRC == 1 ? 0b1000 :
NRF_CRC == 2 ? 0b1100 :
0))); // Mask all interrupts
nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, *rec & 0x7F);
nrf24_write_reg(
nrf24_HANDLE,
REG_FEATURE,
*(rec + 2 + addr_size) >> 2 != 0x33 ?
4 + 1 :
1); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload
if(*(rec + 1) & 0b100) { // ESB
nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, 0x01); // Automatic Retransmission
nrf24_write_reg(nrf24_HANDLE, REG_EN_AA, 0x3F); // Auto acknowledgement
} else {
nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, 0); // Automatic Retransmission
nrf24_write_reg(nrf24_HANDLE, REG_EN_AA, 0); // Auto acknowledgement
}
} else {
nrf24_write_reg(
nrf24_HANDLE,
REG_CONFIG,
@@ -495,85 +558,55 @@ static void prepare_nrf24(bool fsend_packet) {
NRF_DPL ?
4 + 1 :
1); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload
}
if(what_to_do == 3) {
uint8_t* p = APP->log_arr + view_log_arr_idx * LOG_REC_SIZE;
uint8_t addr_size = (*(p + 1) & 0b11) + 2;
nrf24_set_maclen(nrf24_HANDLE, addr_size);
nrf24_set_mac(REG_RX_ADDR_P0, p + 2, addr_size);
memcpy(addrs.addr_P0, p + 2, addr_size);
addrs.addr_count = 1;
addrs.addr_len = addr_size;
nrf24_write_reg(nrf24_HANDLE, RX_PW_P0, *(p + 1) >> 3);
nrf24_write_reg(nrf24_HANDLE, REG_EN_RXADDR, erx_addr);
nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, *p & 0x7F);
nrf24_write_reg(
nrf24_HANDLE,
REG_CONFIG,
0x70 | ((NRF_CRC == 1 ? 0b1000 :
NRF_CRC == 2 ? 0b1100 :
0))); // Mask all interrupts
if(*(p + 1) & 0b100) { // ESB
nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, 0x01); // Automatic Retransmission
nrf24_write_reg(nrf24_HANDLE, REG_EN_AA, 0x3F); // Auto acknowledgement
nrf24_write_reg(
nrf24_HANDLE,
REG_FEATURE,
*(p + 2 + addr_size) >> 2 != 0x33 ?
4 + 1 :
1); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload
} else {
nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, 0); // Automatic Retransmission
nrf24_write_reg(nrf24_HANDLE, REG_EN_AA, 0); // Auto acknowledgement
}
} else {
nrf24_set_maclen(nrf24_HANDLE, adr->addr_len);
nrf24_set_mac(REG_RX_ADDR_P0, adr->addr_P0, adr->addr_len);
uint8_t tmp[5] = {0};
nrf24_read_reg(nrf24_HANDLE, REG_RX_ADDR_P0, tmp, adr->addr_len);
for(uint8_t i = 0; i < adr->addr_len / 2; i++) {
uint8_t tb = tmp[i];
tmp[i] = tmp[adr->addr_len - i - 1];
tmp[adr->addr_len - i - 1] = tb;
}
NRF_ERROR = memcmp(adr->addr_P0, tmp, adr->addr_len) != 0;
FURI_LOG_D(TAG, "Payload: %d", payload);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P0, payload);
if(adr->addr_count > 1) {
nrf24_set_mac(REG_RX_ADDR_P1, adr->addr_P1, adr->addr_len);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P1, payload);
erx_addr |= (1 << 1); // Enable RX_P1
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P1, 0);
if(adr->addr_count > 2) {
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P2, &adr->addr_P2, 1);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P2, payload);
erx_addr |= (1 << 2); // Enable RX_P2
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P2, 0);
if(adr->addr_count > 3) {
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P3, &adr->addr_P3, 1);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P3, payload);
erx_addr |= (1 << 3); // Enable RX_P3
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P3, 0);
if(adr->addr_count > 4) {
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P4, &adr->addr_P4, 1);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P4, payload);
erx_addr |= (1 << 4); // Enable RX_P4
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P4, 0);
if(adr->addr_count > 5) {
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P5, &adr->addr_P5, 1);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P5, payload);
erx_addr |= (1 << 5); // Enable RX_P5
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P5, 0);
nrf24_write_reg(
nrf24_HANDLE, REG_DYNPD, NRF_DPL ? 0x3F : 0); // Enable dynamic payload reg
nrf24_write_reg(nrf24_HANDLE, REG_EN_RXADDR, erx_addr);
nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, NRF_channel);
}
if(adr->addr_count == 0) return;
nrf24_write_reg(nrf24_HANDLE, RX_PW_P0, payload);
nrf24_set_maclen(nrf24_HANDLE, adr->addr_len);
nrf24_set_mac(REG_RX_ADDR_P0, adr->addr_P0, adr->addr_len);
uint8_t tmp[5] = {0};
nrf24_read_reg(nrf24_HANDLE, REG_RX_ADDR_P0, tmp, adr->addr_len);
for(uint8_t i = 0; i < adr->addr_len / 2; i++) {
uint8_t tb = tmp[i];
tmp[i] = tmp[adr->addr_len - i - 1];
tmp[adr->addr_len - i - 1] = tb;
}
NRF_ERROR = memcmp(adr->addr_P0, tmp, adr->addr_len) != 0;
FURI_LOG_D(TAG, "Payload: %d", payload);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P0, payload);
if(adr->addr_count > 1) {
nrf24_set_mac(REG_RX_ADDR_P1, adr->addr_P1, adr->addr_len);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P1, payload);
erx_addr |= (1 << 1); // Enable RX_P1
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P1, 0);
if(adr->addr_count > 2) {
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P2, &adr->addr_P2, 1);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P2, payload);
erx_addr |= (1 << 2); // Enable RX_P2
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P2, 0);
if(adr->addr_count > 3) {
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P3, &adr->addr_P3, 1);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P3, payload);
erx_addr |= (1 << 3); // Enable RX_P3
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P3, 0);
if(adr->addr_count > 4) {
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P4, &adr->addr_P4, 1);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P4, payload);
erx_addr |= (1 << 4); // Enable RX_P4
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P4, 0);
if(adr->addr_count > 5) {
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P5, &adr->addr_P5, 1);
nrf24_write_reg(nrf24_HANDLE, RX_PW_P5, payload);
erx_addr |= (1 << 5); // Enable RX_P5
} else
nrf24_write_reg(nrf24_HANDLE, RX_PW_P5, 0);
nrf24_write_reg(nrf24_HANDLE, REG_EN_RXADDR, erx_addr);
}
nrf24_flush_rx(nrf24_HANDLE);
nrf24_flush_tx(nrf24_HANDLE);
@@ -602,26 +635,6 @@ static void start_scanning() {
start_time = furi_get_tick();
}
/*
bool check_addr_found(uint8_t *pkt)
{
uint8_t idx = 255;
if(addrs_found.addr_count > 0 && memcmp(addrs_found.addr_P0, pkt, addrs_found.addr_len) == 0) { idx = 0; goto x_end; }
if(addrs_found.addr_count > 1 && memcmp(addrs_found.addr_P1, pkt, addrs_found.addr_len - 1) == 0) {
if(addrs_found.addr_P1[addrs_found.addr_len - 1] == pkt[addrs_found.addr_len - 1]) { idx = 1; goto x_end; }
if(addrs_found.addr_count > 2 && addrs_found.addr_P2 == pkt[addrs_found.addr_len - 1]) { idx = 2; goto x_end; }
if(addrs_found.addr_count > 3 && addrs_found.addr_P3 == pkt[addrs_found.addr_len - 1]) { idx = 3; goto x_end; }
if(addrs_found.addr_count > 4 && addrs_found.addr_P4 == pkt[addrs_found.addr_len - 1]) { idx = 4; goto x_end; }
if(addrs_found.addr_count > 5 && addrs_found.addr_P5 == pkt[addrs_found.addr_len - 1]) { idx = 5; goto x_end; }
}
x_end:
if(idx < sizeof(found_total) / sizeof(found_total[0])) {
found_total[idx]++;
return true;
} else return false;
}
*/
// start bitnum = 7
uint32_t calc_crc(uint32_t crc, uint8_t* ptr, uint8_t bitnum, uint16_t bits) {
//uint8_t bitnum = 7;
@@ -775,55 +788,6 @@ bool check_packet(uint8_t* pkt, uint16_t size) {
found_total++;
}
}
/*
if(addrs_found.addr_count == 0) {
memcpy(addrs_found.addr_P0, pkt, addr_size);
addrs_found.addr_len = addr_size;
found_total[0]++;
addrs_found.addr_count++;
} else if(addr_size == addrs_found.addr_len) {
if(!check_addr_found(pkt)) {
if(addrs_found.addr_count == 1) {
memcpy(addrs_found.addr_P1, pkt, addr_size);
found_total[1]++;
addrs_found.addr_count++;
} else if(addrs_found.addr_count == 2) {
if(memcmp(addrs_found.addr_P1, pkt, addr_size - 1) == 0) {
addrs_found.addr_P2 = pkt[addr_size - 1];
found_total[2]++;
addrs_found.addr_count++;
} else if(memcmp(addrs_found.addr_P0, pkt, addr_size - 1) == 0) {
uint8_t tmp[5];
memcpy(tmp, addrs_found.addr_P1, addr_size); // swap P0-P1
memcpy(addrs_found.addr_P1, addrs_found.addr_P0, addr_size);
memcpy(addrs_found.addr_P0, tmp, addr_size);
uint32_t n = found_total[0];
found_total[0] = found_total[1];
found_total[1] = n;
addrs_found.addr_P2 = pkt[addr_size - 1];
found_total[2]++;
addrs_found.addr_count++;
}
} else if(addrs_found.addr_count >= 3) {
if(memcmp(addrs_found.addr_P1, pkt, addr_size - 1) == 0) {
if(addrs_found.addr_count == 3) {
addrs_found.addr_P3 = pkt[addr_size - 1];
found_total[3]++;
addrs_found.addr_count++;
} else if(addrs_found.addr_count == 4) {
addrs_found.addr_P4 = pkt[addr_size - 1];
found_total[4]++;
addrs_found.addr_count++;
} else if(addrs_found.addr_count == 5) {
addrs_found.addr_P5 = pkt[addr_size - 1];
found_total[5]++;
addrs_found.addr_count++;
}
}
}
}
}
*/
}
return found;
@@ -1008,7 +972,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_str(canvas, 10, 30, screen_buf);
if(what_to_do == 1)
snprintf(screen_buf, sizeof(screen_buf), "Min Payl: %d", NRF_Payload_sniff_min);
else if(what_to_do == 3) {
else if(what_to_do >= 2) {
uint8_t* p = APP->log_arr + view_log_arr_idx * LOG_REC_SIZE;
snprintf(
screen_buf,
@@ -1045,11 +1009,11 @@ static void render_callback(Canvas* const canvas, void* ctx) {
if(what_to_do == 1)
snprintf(screen_buf, sizeof(screen_buf), "Start sniff");
else {
uint8_t* p;
if(what_to_do == 3 && log_arr_idx &&
*(p = APP->log_arr + view_log_arr_idx * LOG_REC_SIZE) & 0x80) { // +RAW
uint8_t* p = APP->log_arr + view_log_arr_idx * LOG_REC_SIZE;
if(log_arr_idx && (*p & 0x80)) { // +RAW
snprintf(screen_buf, sizeof(screen_buf), "Start read: ");
add_to_str_hex_bytes(screen_buf, (char*)p + 2, (*(p + 1) & 0b11) + 2);
if(what_to_do == 3) strcpy(screen_buf + strlen(screen_buf) - 2, "* ");
} else
snprintf(
screen_buf,
@@ -1585,7 +1549,7 @@ int32_t nrf24scan_app(void* p) {
case Menu_ok:
if(what_to_do) {
if((addrs.addr_count ||
(what_to_do == 3 && log_arr_idx &&
(what_to_do >= 2 && log_arr_idx &&
*(APP->log_arr + view_log_arr_idx * LOG_REC_SIZE) &
0x80)) ||
what_to_do == 1) {
@@ -1667,4 +1631,4 @@ int32_t nrf24scan_app(void* p) {
if(APP->found) free(APP->found);
free(APP);
return 0;
}
}
@@ -38,6 +38,9 @@
TOTP_CLI_PRINTF( \
"Invalid command arguments. use \"help\" command to get list of available commands")
#define TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE() \
TOTP_CLI_PRINTF("An error has occurred during updating config file\r\n")
/**
* @brief Checks whether user is authenticated and entered correct PIN.
* If user is not authenticated it prompts user to enter correct PIN to authenticate.
@@ -206,11 +206,13 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, token_info, furi_check);
plugin_state->tokens_count++;
totp_config_file_save_new_token(token_info);
if(totp_config_file_save_new_token(token_info) == TotpConfigFileUpdateSuccess) {
TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name);
} else {
TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
}
if(load_generate_token_scene) {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name);
}
@@ -93,14 +93,17 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args,
plugin_state->tokens_list = list_remove(plugin_state->tokens_list, list_node);
plugin_state->tokens_count--;
totp_full_save_config_file(plugin_state);
if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) {
TOTP_CLI_PRINTF("Token \"%s\" has been successfully deleted\r\n", token_info->name);
} else {
TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
}
token_info_free(token_info);
if(activate_generate_token_scene) {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
TOTP_CLI_PRINTF("Token \"%s\" has been successfully deleted\r\n", token_info->name);
token_info_free(token_info);
} else {
TOTP_CLI_PRINTF("User not confirmed\r\n");
}
@@ -147,18 +147,18 @@ void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, C
}
if(token_updated) {
totp_full_save_config_file(plugin_state);
if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) {
TOTP_CLI_PRINTF("Token \"%s\" has been successfully updated\r\n", token_info->name);
} else {
TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
}
} else {
TOTP_CLI_PRINT_INVALID_ARGUMENTS();
}
if(activate_generate_token_scene) {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
if(token_updated) {
TOTP_CLI_PRINTF("Token \"%s\" has been successfully updated\r\n", token_info->name);
} else {
TOTP_CLI_PRINT_INVALID_ARGUMENTS();
}
furi_string_free(temp_str);
}
@@ -86,15 +86,18 @@ void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString*
}
plugin_state->notification_method = new_method;
totp_config_file_update_notification_method(new_method);
if(totp_config_file_update_notification_method(new_method) ==
TotpConfigFileUpdateSuccess) {
TOTP_CLI_PRINTF("Notification method is set to ");
totp_cli_command_notification_print_method(new_method);
cli_nl();
} else {
TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
}
if(previous_scene != TotpSceneNone) {
totp_scene_director_activate_scene(plugin_state, previous_scene, NULL);
}
TOTP_CLI_PRINTF("Notification method is set to ");
totp_cli_command_notification_print_method(new_method);
cli_nl();
} else {
TOTP_CLI_PRINTF("Current notification method is ");
totp_cli_command_notification_print_method(plugin_state->notification_method);
@@ -134,8 +134,14 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl
plugin_state->crypto_verify_data = NULL;
}
totp_crypto_seed_iv(
plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length);
if(!totp_crypto_seed_iv(
plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length)) {
memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE);
TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
break;
}
memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE);
TOTP_LIST_FOREACH(plugin_state->tokens_list, node, {
TokenInfo* token_info = node->data;
@@ -152,15 +158,18 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl
free(plain_token);
});
totp_full_save_config_file(plugin_state);
TOTP_CLI_DELETE_LAST_LINE();
if(do_change) {
TOTP_CLI_PRINTF("PIN has been successfully changed\r\n");
} else if(do_remove) {
TOTP_CLI_PRINTF("PIN has been successfully removed\r\n");
if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) {
if(do_change) {
TOTP_CLI_PRINTF("PIN has been successfully changed\r\n");
} else if(do_remove) {
TOTP_CLI_PRINTF("PIN has been successfully removed\r\n");
}
} else {
TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
}
} while(false);
if(load_generate_token_scene) {
@@ -33,8 +33,11 @@ void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* arg
float tz = strtof(furi_string_get_cstr(temp_str), NULL);
if(tz >= -12.75f && tz <= 12.75f) {
plugin_state->timezone_offset = tz;
totp_config_file_update_timezone_offset(tz);
TOTP_CLI_PRINTF("Timezone is set to %f\r\n", tz);
if(totp_config_file_update_timezone_offset(tz) == TotpConfigFileUpdateSuccess) {
TOTP_CLI_PRINTF("Timezone is set to %f\r\n", tz);
} else {
TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE();
}
if(plugin_state->current_scene == TotpSceneGenerateToken) {
totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
+414 -166
View File
@@ -9,6 +9,8 @@
#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("apps_data/authenticator")
#define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf"
#define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup"
#define CONFIG_FILE_TEMP_PATH CONFIG_FILE_PATH ".tmp"
#define CONFIG_FILE_ORIG_PATH CONFIG_FILE_PATH ".orig"
#define CONFIG_FILE_PATH_PREVIOUS EXT_PATH("apps/Misc") "/totp.conf"
static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) {
@@ -36,15 +38,38 @@ static void token_info_set_algo_from_str(TokenInfo* token_info, const FuriString
}
}
Storage* totp_open_storage() {
/**
* @brief Opens storage record
* @return Storage record
*/
static Storage* totp_open_storage() {
return furi_record_open(RECORD_STORAGE);
}
void totp_close_storage() {
/**
* @brief Closes storage record
*/
static void totp_close_storage() {
furi_record_close(RECORD_STORAGE);
}
FlipperFormat* totp_open_config_file(Storage* storage) {
/**
* @brief Closes config file
* @param file config file reference
*/
static void totp_close_config_file(FlipperFormat* file) {
if(file == NULL) return;
flipper_format_file_close(file);
flipper_format_free(file);
}
/**
* @brief Opens or creates TOTP application standard config file
* @param storage storage record to use
* @param[out] file opened config file
* @return Config file open result
*/
static TotpConfigFileOpenResult totp_open_config_file(Storage* storage, FlipperFormat** file) {
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
if(storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK) {
@@ -52,7 +77,7 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
if(!flipper_format_file_open_existing(fff_data_file, CONFIG_FILE_PATH)) {
FURI_LOG_E(LOGGING_TAG, "Error opening existing file %s", CONFIG_FILE_PATH);
totp_close_config_file(fff_data_file);
return NULL;
return TotpConfigFileOpenError;
}
} else if(storage_common_stat(storage, CONFIG_FILE_PATH_PREVIOUS, NULL) == FSE_OK) {
FURI_LOG_D(LOGGING_TAG, "Old config file %s found", CONFIG_FILE_PATH_PREVIOUS);
@@ -63,15 +88,17 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
CONFIG_FILE_DIRECTORY_PATH);
if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) {
FURI_LOG_E(LOGGING_TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH);
return NULL;
totp_close_config_file(fff_data_file);
return TotpConfigFileOpenError;
}
}
if(storage_common_rename(storage, CONFIG_FILE_PATH_PREVIOUS, CONFIG_FILE_PATH) != FSE_OK) {
FURI_LOG_E(LOGGING_TAG, "Error moving config to %s", CONFIG_FILE_PATH);
return NULL;
totp_close_config_file(fff_data_file);
return TotpConfigFileOpenError;
}
FURI_LOG_I(LOGGING_TAG, "Applied config file path migration");
return totp_open_config_file(storage);
return totp_open_config_file(storage, file);
} else {
FURI_LOG_D(LOGGING_TAG, "Config file %s is not found. Will create new.", CONFIG_FILE_PATH);
if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) {
@@ -81,14 +108,14 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
CONFIG_FILE_DIRECTORY_PATH);
if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) {
FURI_LOG_E(LOGGING_TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH);
return NULL;
return TotpConfigFileOpenError;
}
}
if(!flipper_format_file_open_new(fff_data_file, CONFIG_FILE_PATH)) {
totp_close_config_file(fff_data_file);
FURI_LOG_E(LOGGING_TAG, "Error creating new file %s", CONFIG_FILE_PATH);
return NULL;
return TotpConfigFileOpenError;
}
flipper_format_write_header_cstr(
@@ -153,228 +180,415 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
if(!flipper_format_rewind(fff_data_file)) {
totp_close_config_file(fff_data_file);
FURI_LOG_E(LOGGING_TAG, "Rewind error");
return NULL;
return TotpConfigFileOpenError;
}
}
return fff_data_file;
*file = fff_data_file;
return TotpConfigFileOpenSuccess;
}
void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) {
flipper_format_seek_to_end(file);
flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name);
bool token_is_valid = token_info->token != NULL && token_info->token_length > 0;
if(!token_is_valid) {
flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!");
TotpConfigFileUpdateResult
totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) {
TotpConfigFileUpdateResult update_result;
do {
if(!flipper_format_seek_to_end(file)) {
update_result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name)) {
update_result = TotpConfigFileUpdateError;
break;
}
bool token_is_valid = token_info->token != NULL && token_info->token_length > 0;
if(!token_is_valid &&
!flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!")) {
update_result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_write_hex(
file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length)) {
update_result = TotpConfigFileUpdateError;
break;
}
if(!token_is_valid && !flipper_format_write_comment_cstr(file, "!!! WARNING END !!!")) {
update_result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_write_string_cstr(
file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info))) {
update_result = TotpConfigFileUpdateError;
break;
}
uint32_t tmp_uint32 = token_info->digits;
if(!flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1)) {
update_result = TotpConfigFileUpdateError;
break;
}
update_result = TotpConfigFileUpdateSuccess;
} while(false);
return update_result;
}
TotpConfigFileUpdateResult totp_config_file_save_new_token(const TokenInfo* token_info) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file;
TotpConfigFileUpdateResult update_result;
if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) {
do {
if(totp_config_file_save_new_token_i(file, token_info) !=
TotpConfigFileUpdateSuccess) {
update_result = TotpConfigFileUpdateError;
break;
}
update_result = TotpConfigFileUpdateSuccess;
} while(false);
totp_close_config_file(file);
} else {
update_result = TotpConfigFileUpdateError;
}
flipper_format_write_hex(
file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length);
if(!token_is_valid) {
flipper_format_write_comment_cstr(file, "!!! WARNING END !!!");
totp_close_storage();
return update_result;
}
TotpConfigFileUpdateResult totp_config_file_update_timezone_offset(float new_timezone_offset) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file;
TotpConfigFileUpdateResult update_result;
if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) {
do {
if(!flipper_format_insert_or_update_float(
file, TOTP_CONFIG_KEY_TIMEZONE, &new_timezone_offset, 1)) {
update_result = TotpConfigFileUpdateError;
break;
}
update_result = TotpConfigFileUpdateSuccess;
} while(false);
totp_close_config_file(file);
} else {
update_result = TotpConfigFileUpdateError;
}
flipper_format_write_string_cstr(
file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info));
uint32_t tmp_uint32 = token_info->digits;
flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1);
}
void totp_config_file_save_new_token(const TokenInfo* token_info) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file = totp_open_config_file(cfg_storage);
totp_config_file_save_new_token_i(file, token_info);
totp_close_config_file(file);
totp_close_storage();
return update_result;
}
void totp_config_file_update_timezone_offset(float new_timezone_offset) {
TotpConfigFileUpdateResult
totp_config_file_update_notification_method(NotificationMethod new_notification_method) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file = totp_open_config_file(cfg_storage);
FlipperFormat* file;
TotpConfigFileUpdateResult update_result;
flipper_format_insert_or_update_float(file, TOTP_CONFIG_KEY_TIMEZONE, &new_timezone_offset, 1);
if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) {
do {
uint32_t tmp_uint32 = new_notification_method;
if(!flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
update_result = TotpConfigFileUpdateError;
break;
}
update_result = TotpConfigFileUpdateSuccess;
} while(false);
totp_close_config_file(file);
} else {
update_result = TotpConfigFileUpdateError;
}
totp_close_config_file(file);
totp_close_storage();
return update_result;
}
void totp_config_file_update_notification_method(NotificationMethod new_notification_method) {
TotpConfigFileUpdateResult totp_config_file_update_user_settings(const PluginState* plugin_state) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file = totp_open_config_file(cfg_storage);
FlipperFormat* file;
TotpConfigFileUpdateResult update_result;
if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) {
do {
if(!flipper_format_insert_or_update_float(
file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) {
update_result = TotpConfigFileUpdateError;
break;
}
uint32_t tmp_uint32 = plugin_state->notification_method;
if(!flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
update_result = TotpConfigFileUpdateError;
break;
}
uint32_t tmp_uint32 = new_notification_method;
flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1);
update_result = TotpConfigFileUpdateSuccess;
} while(false);
totp_close_config_file(file);
} else {
update_result = TotpConfigFileUpdateError;
}
totp_close_config_file(file);
totp_close_storage();
return update_result;
}
void totp_config_file_update_user_settings(const PluginState* plugin_state) {
Storage* cfg_storage = totp_open_storage();
FlipperFormat* file = totp_open_config_file(cfg_storage);
flipper_format_insert_or_update_float(
file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1);
uint32_t tmp_uint32 = plugin_state->notification_method;
flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1);
totp_close_config_file(file);
totp_close_storage();
}
void totp_full_save_config_file(const PluginState* const plugin_state) {
TotpConfigFileUpdateResult totp_full_save_config_file(const PluginState* const plugin_state) {
Storage* storage = totp_open_storage();
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
TotpConfigFileUpdateResult result = TotpConfigFileUpdateSuccess;
flipper_format_file_open_always(fff_data_file, CONFIG_FILE_PATH);
flipper_format_write_header_cstr(
fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION);
flipper_format_write_hex(
fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE);
flipper_format_write_hex(
fff_data_file,
TOTP_CONFIG_KEY_CRYPTO_VERIFY,
plugin_state->crypto_verify_data,
plugin_state->crypto_verify_data_length);
flipper_format_write_float(
fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1);
flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1);
uint32_t tmp_uint32 = plugin_state->notification_method;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1);
do {
if(!flipper_format_file_open_always(fff_data_file, CONFIG_FILE_TEMP_PATH)) {
result = TotpConfigFileUpdateError;
break;
}
TOTP_LIST_FOREACH(plugin_state->tokens_list, node, {
const TokenInfo* token_info = node->data;
totp_config_file_save_new_token_i(fff_data_file, token_info);
});
if(!flipper_format_write_header_cstr(
fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION)) {
result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_write_hex(
fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) {
result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_write_hex(
fff_data_file,
TOTP_CONFIG_KEY_CRYPTO_VERIFY,
plugin_state->crypto_verify_data,
plugin_state->crypto_verify_data_length)) {
result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_write_float(
fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) {
result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_write_bool(
fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
result = TotpConfigFileUpdateError;
break;
}
uint32_t tmp_uint32 = plugin_state->notification_method;
if(!flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
result = TotpConfigFileUpdateError;
break;
}
bool tokens_written = true;
TOTP_LIST_FOREACH(plugin_state->tokens_list, node, {
const TokenInfo* token_info = node->data;
tokens_written = tokens_written &&
totp_config_file_save_new_token_i(fff_data_file, token_info) ==
TotpConfigFileUpdateSuccess;
});
if(!tokens_written) {
result = TotpConfigFileUpdateError;
break;
}
} while(false);
totp_close_config_file(fff_data_file);
if(result == TotpConfigFileUpdateSuccess) {
if(storage_file_exists(storage, CONFIG_FILE_ORIG_PATH)) {
storage_simply_remove(storage, CONFIG_FILE_ORIG_PATH);
}
if(storage_common_rename(storage, CONFIG_FILE_PATH, CONFIG_FILE_ORIG_PATH) != FSE_OK) {
result = TotpConfigFileUpdateError;
} else if(storage_common_rename(storage, CONFIG_FILE_TEMP_PATH, CONFIG_FILE_PATH) != FSE_OK) {
result = TotpConfigFileUpdateError;
} else if(!storage_simply_remove(storage, CONFIG_FILE_ORIG_PATH)) {
result = TotpConfigFileUpdateError;
}
}
totp_close_storage();
return result;
}
void totp_config_file_load_base(PluginState* const plugin_state) {
TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_state) {
Storage* storage = totp_open_storage();
FlipperFormat* fff_data_file = totp_open_config_file(storage);
FlipperFormat* fff_data_file;
TotpConfigFileOpenResult result;
if((result = totp_open_config_file(storage, &fff_data_file)) != TotpConfigFileOpenSuccess) {
totp_close_storage();
return result;
}
plugin_state->timezone_offset = 0;
FuriString* temp_str = furi_string_alloc();
uint32_t file_version;
if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) {
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
furi_string_free(temp_str);
return;
}
if(file_version < CONFIG_FILE_ACTUAL_VERSION) {
FURI_LOG_I(
LOGGING_TAG,
"Obsolete config file version detected. Current version: %" PRIu32
"; Actual version: %" PRId16,
file_version,
CONFIG_FILE_ACTUAL_VERSION);
totp_close_config_file(fff_data_file);
if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) {
storage_simply_remove(storage, CONFIG_FILE_BACKUP_PATH);
do {
uint32_t file_version;
if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) {
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
result = TotpConfigFileOpenError;
break;
}
if(storage_common_copy(storage, CONFIG_FILE_PATH, CONFIG_FILE_BACKUP_PATH) == FSE_OK) {
FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH);
fff_data_file = totp_open_config_file(storage);
FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage);
flipper_format_file_open_existing(fff_backup_data_file, CONFIG_FILE_BACKUP_PATH);
if(file_version < CONFIG_FILE_ACTUAL_VERSION) {
FURI_LOG_I(
LOGGING_TAG,
"Obsolete config file version detected. Current version: %" PRIu32
"; Actual version: %" PRId16,
file_version,
CONFIG_FILE_ACTUAL_VERSION);
totp_close_config_file(fff_data_file);
if(file_version == 1) {
if(totp_config_migrate_v1_to_v2(fff_data_file, fff_backup_data_file)) {
FURI_LOG_I(LOGGING_TAG, "Applied migration from v1 to v2");
} else {
FURI_LOG_W(LOGGING_TAG, "An error occurred during migration from v1 to v2");
}
if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) {
storage_simply_remove(storage, CONFIG_FILE_BACKUP_PATH);
}
flipper_format_file_close(fff_backup_data_file);
flipper_format_free(fff_backup_data_file);
flipper_format_rewind(fff_data_file);
} else {
FURI_LOG_E(
LOGGING_TAG,
"An error occurred during taking backup of %s into %s before migration",
CONFIG_FILE_PATH,
CONFIG_FILE_BACKUP_PATH);
if(storage_common_copy(storage, CONFIG_FILE_PATH, CONFIG_FILE_BACKUP_PATH) == FSE_OK) {
FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH);
if(totp_open_config_file(storage, &fff_data_file) != TotpConfigFileOpenSuccess) {
result = TotpConfigFileOpenError;
break;
}
FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage);
if(!flipper_format_file_open_existing(
fff_backup_data_file, CONFIG_FILE_BACKUP_PATH)) {
flipper_format_file_close(fff_backup_data_file);
flipper_format_free(fff_backup_data_file);
result = TotpConfigFileOpenError;
break;
}
if(file_version == 1) {
if(totp_config_migrate_v1_to_v2(fff_data_file, fff_backup_data_file)) {
FURI_LOG_I(LOGGING_TAG, "Applied migration from v1 to v2");
} else {
FURI_LOG_W(
LOGGING_TAG, "An error occurred during migration from v1 to v2");
result = TotpConfigFileOpenError;
break;
}
}
flipper_format_file_close(fff_backup_data_file);
flipper_format_free(fff_backup_data_file);
flipper_format_rewind(fff_data_file);
} else {
FURI_LOG_E(
LOGGING_TAG,
"An error occurred during taking backup of %s into %s before migration",
CONFIG_FILE_PATH,
CONFIG_FILE_BACKUP_PATH);
result = TotpConfigFileOpenError;
break;
}
}
}
if(!flipper_format_read_hex(
fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) {
FURI_LOG_D(LOGGING_TAG, "Missing base IV");
}
flipper_format_rewind(fff_data_file);
uint32_t crypto_size;
if(flipper_format_get_value_count(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) &&
crypto_size > 0) {
plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size);
furi_check(plugin_state->crypto_verify_data != NULL);
plugin_state->crypto_verify_data_length = crypto_size;
if(!flipper_format_read_hex(
fff_data_file,
TOTP_CONFIG_KEY_CRYPTO_VERIFY,
plugin_state->crypto_verify_data,
crypto_size)) {
FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token");
free(plugin_state->crypto_verify_data);
fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) {
FURI_LOG_D(LOGGING_TAG, "Missing base IV");
}
if(!flipper_format_rewind(fff_data_file)) {
result = TotpConfigFileOpenError;
break;
}
uint32_t crypto_size;
if(flipper_format_get_value_count(
fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) &&
crypto_size > 0) {
plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size);
furi_check(plugin_state->crypto_verify_data != NULL);
plugin_state->crypto_verify_data_length = crypto_size;
if(!flipper_format_read_hex(
fff_data_file,
TOTP_CONFIG_KEY_CRYPTO_VERIFY,
plugin_state->crypto_verify_data,
crypto_size)) {
FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token");
free(plugin_state->crypto_verify_data);
plugin_state->crypto_verify_data = NULL;
plugin_state->crypto_verify_data_length = 0;
}
} else {
plugin_state->crypto_verify_data = NULL;
plugin_state->crypto_verify_data_length = 0;
}
} else {
plugin_state->crypto_verify_data = NULL;
plugin_state->crypto_verify_data_length = 0;
}
flipper_format_rewind(fff_data_file);
if(!flipper_format_rewind(fff_data_file)) {
result = TotpConfigFileOpenError;
break;
}
if(!flipper_format_read_float(
fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) {
plugin_state->timezone_offset = 0;
FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0");
}
if(!flipper_format_read_float(
fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) {
plugin_state->timezone_offset = 0;
FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0");
}
flipper_format_rewind(fff_data_file);
if(!flipper_format_rewind(fff_data_file)) {
result = TotpConfigFileOpenError;
break;
}
if(!flipper_format_read_bool(
fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
plugin_state->pin_set = true;
}
if(!flipper_format_read_bool(
fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
plugin_state->pin_set = true;
}
flipper_format_rewind(fff_data_file);
flipper_format_rewind(fff_data_file);
uint32_t tmp_uint32;
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
}
uint32_t tmp_uint32;
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
}
plugin_state->notification_method = tmp_uint32;
plugin_state->notification_method = tmp_uint32;
} while(false);
furi_string_free(temp_str);
totp_close_config_file(fff_data_file);
totp_close_storage();
return result;
}
TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) {
Storage* storage = totp_open_storage();
FlipperFormat* fff_data_file = totp_open_config_file(storage);
FlipperFormat* fff_data_file;
if(totp_open_config_file(storage, &fff_data_file) != TotpConfigFileOpenSuccess) {
totp_close_storage();
return TokenLoadingResultError;
}
FuriString* temp_str = furi_string_alloc();
uint32_t temp_data32;
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
totp_close_storage();
furi_string_free(temp_str);
return TokenLoadingResultError;
}
@@ -478,8 +692,42 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
return result;
}
void totp_close_config_file(FlipperFormat* file) {
if(file == NULL) return;
flipper_format_file_close(file);
flipper_format_free(file);
}
TotpConfigFileUpdateResult
totp_config_file_update_crypto_signatures(const PluginState* plugin_state) {
Storage* storage = totp_open_storage();
FlipperFormat* config_file;
TotpConfigFileUpdateResult update_result;
if(totp_open_config_file(storage, &config_file) == TotpConfigFileOpenSuccess) {
do {
if(!flipper_format_insert_or_update_hex(
config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE)) {
update_result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_insert_or_update_hex(
config_file,
TOTP_CONFIG_KEY_CRYPTO_VERIFY,
plugin_state->crypto_verify_data,
plugin_state->crypto_verify_data_length)) {
update_result = TotpConfigFileUpdateError;
break;
}
if(!flipper_format_insert_or_update_bool(
config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
update_result = TotpConfigFileUpdateError;
break;
}
update_result = TotpConfigFileUpdateSuccess;
} while(false);
totp_close_config_file(config_file);
} else {
update_result = TotpConfigFileUpdateError;
}
totp_close_storage();
return update_result;
}
@@ -7,6 +7,8 @@
#include "constants.h"
typedef uint8_t TokenLoadingResult;
typedef uint8_t TotpConfigFileOpenResult;
typedef uint8_t TotpConfigFileUpdateResult;
/**
* @brief Token loading results
@@ -29,40 +31,48 @@ enum TokenLoadingResults {
};
/**
* @brief Opens storage record
* @return Storage record
* @brief Config file opening result
*/
Storage* totp_open_storage();
enum TotpConfigFileOpenResults {
/**
* @brief Config file opened successfully
*/
TotpConfigFileOpenSuccess = 0,
/**
* @brief An error has occurred during opening config file
*/
TotpConfigFileOpenError = 1
};
/**
* @brief Closes storage record
* @brief Config file updating result
*/
void totp_close_storage();
enum TotpConfigFileUpdateResults {
/**
* @brief Config file updated successfully
*/
TotpConfigFileUpdateSuccess,
/**
* @brief Opens or creates TOTP application standard config file
* @param storage storage record to use
* @return Config file reference
*/
FlipperFormat* totp_open_config_file(Storage* storage);
/**
* @brief Closes config file
* @param file config file reference
*/
void totp_close_config_file(FlipperFormat* file);
/**
* @brief An error has occurred during updating config file
*/
TotpConfigFileUpdateError
};
/**
* @brief Saves all the settings and tokens to an application config file
* @param plugin_state application state
* @return Config file update result
*/
void totp_full_save_config_file(const PluginState* const plugin_state);
TotpConfigFileUpdateResult totp_full_save_config_file(const PluginState* const plugin_state);
/**
* @brief Loads basic information from an application config file into application state without loading all the tokens
* @param plugin_state application state
* @return Config file open result
*/
void totp_config_file_load_base(PluginState* const plugin_state);
TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_state);
/**
* @brief Loads tokens from an application config file into application state
@@ -74,23 +84,36 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
/**
* @brief Add new token to the end of the application config file
* @param token_info token information to be saved
* @return Config file update result
*/
void totp_config_file_save_new_token(const TokenInfo* token_info);
TotpConfigFileUpdateResult totp_config_file_save_new_token(const TokenInfo* token_info);
/**
* @brief Updates timezone offset in an application config file
* @param new_timezone_offset new timezone offset to be set
* @return Config file update result
*/
void totp_config_file_update_timezone_offset(float new_timezone_offset);
TotpConfigFileUpdateResult totp_config_file_update_timezone_offset(float new_timezone_offset);
/**
* @brief Updates notification method in an application config file
* @param new_notification_method new notification method to be set
* @return Config file update result
*/
void totp_config_file_update_notification_method(NotificationMethod new_notification_method);
TotpConfigFileUpdateResult
totp_config_file_update_notification_method(NotificationMethod new_notification_method);
/**
* @brief Updates application user settings
* @param plugin_state application state
* @return Config file update result
*/
void totp_config_file_update_user_settings(const PluginState* plugin_state);
TotpConfigFileUpdateResult totp_config_file_update_user_settings(const PluginState* plugin_state);
/**
* @brief Updates crypto signatures information
* @param plugin_state application state
* @return Config file update result
*/
TotpConfigFileUpdateResult
totp_config_file_update_crypto_signatures(const PluginState* plugin_state);
@@ -61,7 +61,7 @@ uint8_t* totp_crypto_decrypt(
return decrypted_data;
}
void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) {
bool totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) {
if(plugin_state->crypto_verify_data == NULL) {
FURI_LOG_D(LOGGING_TAG, "Generating new IV");
furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE);
@@ -94,13 +94,12 @@ void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t
}
}
bool result = true;
if(plugin_state->crypto_verify_data == NULL) {
FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data");
plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
furi_check(plugin_state->crypto_verify_data != NULL);
plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH;
Storage* storage = totp_open_storage();
FlipperFormat* config_file = totp_open_config_file(storage);
plugin_state->crypto_verify_data = totp_crypto_encrypt(
(uint8_t*)CRYPTO_VERIFY_KEY,
@@ -108,19 +107,13 @@ void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t
&plugin_state->iv[0],
&plugin_state->crypto_verify_data_length);
flipper_format_insert_or_update_hex(
config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE);
flipper_format_insert_or_update_hex(
config_file,
TOTP_CONFIG_KEY_CRYPTO_VERIFY,
plugin_state->crypto_verify_data,
CRYPTO_VERIFY_KEY_LENGTH);
plugin_state->pin_set = pin != NULL && pin_length > 0;
flipper_format_insert_or_update_bool(
config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1);
totp_close_config_file(config_file);
totp_close_storage();
result = totp_config_file_update_crypto_signatures(plugin_state) ==
TotpConfigFileUpdateSuccess;
}
return result;
}
bool totp_crypto_verify_key(const PluginState* plugin_state) {
@@ -35,8 +35,9 @@ uint8_t* totp_crypto_decrypt(
* @param plugin_state application state
* @param pin user's PIN
* @param pin_length user's PIN length
* @return \c true on success; \c false otherwise
*/
void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length);
bool totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length);
/**
* @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption
@@ -18,8 +18,6 @@
/* Written by Simon Josefsson. The interface was inspired by memxor
in Niels Möller's Nettle. */
/* #include <config.h> */
#include "memxor.h"
void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) {
+35 -19
View File
@@ -15,6 +15,7 @@
#include "types/common.h"
#include "ui/scene_director.h"
#include "ui/constants.h"
#include "ui/common_dialogs.h"
#include "services/crypto/crypto.h"
#include "cli/cli.h"
@@ -36,17 +37,7 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu
furi_message_queue_put(event_queue, &event, FuriWaitForever);
}
static bool totp_plugin_state_init(PluginState* const plugin_state) {
plugin_state->gui = furi_record_open(RECORD_GUI);
plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION);
plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS);
totp_config_file_load_base(plugin_state);
totp_cli_register_command_handler(plugin_state);
totp_scene_director_init_scenes(plugin_state);
static bool totp_activate_initial_scene(PluginState* const plugin_state) {
if(plugin_state->crypto_verify_data == NULL) {
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "No", NULL, "Yes");
@@ -63,13 +54,19 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) {
if(dialog_result == DialogMessageButtonRight) {
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
} else {
totp_crypto_seed_iv(plugin_state, NULL, 0);
if(!totp_crypto_seed_iv(plugin_state, NULL, 0)) {
totp_dialogs_config_loading_error(plugin_state);
return false;
}
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
} else if(plugin_state->pin_set) {
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
} else {
totp_crypto_seed_iv(plugin_state, NULL, 0);
if(!totp_crypto_seed_iv(plugin_state, NULL, 0)) {
totp_dialogs_config_loading_error(plugin_state);
return false;
}
if(totp_crypto_verify_key(plugin_state)) {
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
} else {
@@ -94,13 +91,20 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) {
return true;
}
static bool totp_plugin_state_init(PluginState* const plugin_state) {
plugin_state->gui = furi_record_open(RECORD_GUI);
plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION);
plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS);
if(totp_config_file_load_base(plugin_state) != TotpConfigFileOpenSuccess) {
totp_dialogs_config_loading_error(plugin_state);
return false;
}
return true;
}
static void totp_plugin_state_free(PluginState* plugin_state) {
totp_cli_unregister_command_handler();
totp_scene_director_deactivate_active_scene(plugin_state);
totp_scene_director_dispose(plugin_state);
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION);
furi_record_close(RECORD_DIALOGS);
@@ -139,6 +143,14 @@ int32_t totp_app() {
return 255;
}
totp_cli_register_command_handler(plugin_state);
totp_scene_director_init_scenes(plugin_state);
if(!totp_activate_initial_scene(plugin_state)) {
FURI_LOG_E(LOGGING_TAG, "An error ocurred during activating initial scene\r\n");
totp_plugin_state_free(plugin_state);
return 253;
}
// Set system callbacks
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
@@ -171,6 +183,10 @@ int32_t totp_app() {
release_mutex(&state_mutex, plugin_state_m);
}
totp_cli_unregister_command_handler();
totp_scene_director_deactivate_active_scene(plugin_state);
totp_scene_director_dispose(plugin_state);
view_port_enabled_set(view_port, false);
gui_remove_view_port(plugin_state->gui, view_port);
view_port_free(view_port);
@@ -0,0 +1,20 @@
#include "common_dialogs.h"
#include "constants.h"
static DialogMessageButton totp_dialogs_common(PluginState* plugin_state, const char* text) {
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "Exit", NULL, NULL);
dialog_message_set_text(
message, text, SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter);
DialogMessageButton result = dialog_message_show(plugin_state->dialogs_app, message);
dialog_message_free(message);
return result;
}
DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state) {
return totp_dialogs_common(plugin_state, "An error has occurred\nduring loading config file");
}
DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state) {
return totp_dialogs_common(plugin_state, "An error has occurred\nduring updating config file");
}
@@ -0,0 +1,7 @@
#pragma once
#include <dialogs/dialogs.h>
#include "../types/plugin_state.h"
DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state);
DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state);
@@ -7,6 +7,7 @@
#include "../../../lib/list/list.h"
#include "../../../services/config/config.h"
#include "../../ui_controls.h"
#include "../../common_dialogs.h"
#include "../../../lib/roll_value/roll_value.h"
#include "../../../types/nullable.h"
#include "../generate_token/totp_scene_generate_token.h"
@@ -248,7 +249,11 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check);
plugin_state->tokens_count++;
totp_config_file_save_new_token(tokenInfo);
if(totp_config_file_save_new_token(tokenInfo) != TotpConfigFileUpdateSuccess) {
token_info_free(tokenInfo);
totp_dialogs_config_updating_error(plugin_state);
return false;
}
GenerateTokenSceneContext generate_scene_context = {
.current_token_index = plugin_state->tokens_count - 1};
@@ -2,6 +2,7 @@
#include <math.h>
#include <Authenticator_icons.h>
#include "../../ui_controls.h"
#include "../../common_dialogs.h"
#include "../../scene_director.h"
#include "../token_menu/totp_scene_token_menu.h"
#include "../../constants.h"
@@ -202,7 +203,12 @@ bool totp_scene_app_settings_handle_event(
NotificationMethodNone) |
(scene_state->notification_vibro ? NotificationMethodVibro :
NotificationMethodNone);
totp_config_file_update_user_settings(plugin_state);
if(totp_config_file_update_user_settings(plugin_state) !=
TotpConfigFileUpdateSuccess) {
totp_dialogs_config_updating_error(plugin_state);
return false;
}
if(!scene_state->current_token_index.is_null) {
TokenMenuSceneContext generate_scene_context = {
@@ -128,7 +128,7 @@ static void int_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount
str[len] = '\0';
}
TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
switch(algo) {
case SHA1:
return TOTP_ALGO_SHA1;
@@ -143,7 +143,7 @@ TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
return NULL;
}
void update_totp_params(PluginState* const plugin_state) {
static void update_totp_params(PluginState* const plugin_state) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
if(scene_state->current_token_index < plugin_state->tokens_count) {
@@ -2,6 +2,7 @@
#include <gui/gui.h>
#include <dialogs/dialogs.h>
#include "../../ui_controls.h"
#include "../../common_dialogs.h"
#include "../../constants.h"
#include "../../scene_director.h"
#include "../../../services/config/config.h"
@@ -156,7 +157,10 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt
furi_check(tokenInfo != NULL);
token_info_free(tokenInfo);
totp_full_save_config_file(plugin_state);
if(totp_full_save_config_file(plugin_state) != TotpConfigFileUpdateSuccess) {
totp_dialogs_config_updating_error(plugin_state);
return false;
}
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
}
break;
@@ -0,0 +1,5 @@
SNIFF
ESB: 1
CRC: 2
P0: 00AA
P1: 0055
@@ -0,0 +1,6 @@
SNIFF
ESB: 1
CRC: 2
P0: FFAA
P1: 0055
P2: AA