#include "flipbip_file.h" #include #include #include "../helpers/flipbip_string.h" // From: lib/crypto #include #include // #define FLIPBIP_APP_BASE_FOLDER APP_DATA_PATH("flipbip") #define FLIPBIP_APP_BASE_FOLDER EXT_PATH("apps_data/flipbip") #define FLIPBIP_APP_BASE_FOLDER_PATH(path) FLIPBIP_APP_BASE_FOLDER "/" path #define FLIPBIP_DAT_FILE_NAME ".flipbip.dat" // #define FLIPBIP_DAT_FILE_NAME ".flipbip.dat.txt" #define FLIPBIP_DAT_FILE_NAME_BAK ".flipbip.dat.bak" #define FLIPBIP_KEY_FILE_NAME ".flipbip.key" // #define FLIPBIP_KEY_FILE_NAME ".flipbip.key.txt" #define FLIPBIP_KEY_FILE_NAME_BAK ".flipbip.key.bak" #define FLIPBIP_DAT_PATH FLIPBIP_APP_BASE_FOLDER_PATH(FLIPBIP_DAT_FILE_NAME) #define FLIPBIP_DAT_PATH_BAK FLIPBIP_APP_BASE_FOLDER_PATH(FLIPBIP_DAT_FILE_NAME_BAK) #define FLIPBIP_KEY_PATH FLIPBIP_APP_BASE_FOLDER_PATH(FLIPBIP_KEY_FILE_NAME) #define FLIPBIP_KEY_PATH_BAK FLIPBIP_APP_BASE_FOLDER_PATH(FLIPBIP_KEY_FILE_NAME_BAK) const char* TEXT_QRFILE = "Filetype: QRCode\n" "Version: 0\n" "Message: "; // 37 chars + 1 null #define FILE_HLEN 4 #define FILE_KLEN 256 #define FILE_SLEN 512 #define FILE_MAX_PATH_LEN 48 #define FILE_MAX_QRFILE_CONTENT 90 const char* FILE_HSTR = "fb01"; const char* FILE_K1 = "fb0131d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a" "baefe6d9ceb651842260e0d1e05e3b90d15e7d5ffaaabc0207bf200a117793a2"; bool flipbip_load_file( char* settings, size_t slen, const FlipBipFile file_type, const char* file_name) { bool ret = false; const char* path; char path_buf[FILE_MAX_PATH_LEN] = {0}; if(file_type == FlipBipFileKey) { path = FLIPBIP_KEY_PATH; } else if(file_type == FlipBipFileDat) { path = FLIPBIP_DAT_PATH; } else { strcpy(path_buf, FLIPBIP_APP_BASE_FOLDER); // 22 strcpy(path_buf + strlen(path_buf), "/"); strcpy(path_buf + strlen(path_buf), file_name); path = path_buf; } Storage* fs_api = furi_record_open(RECORD_STORAGE); File* settings_file = storage_file_alloc(fs_api); if(storage_file_open(settings_file, path, FSAM_READ, FSOM_OPEN_EXISTING)) { char chr; size_t i = 0; while((storage_file_read(settings_file, &chr, 1) == 1) && !storage_file_eof(settings_file) && !isspace(chr)) { if(i < slen) { settings[i] = chr; } i++; } ret = true; } else { memzero(settings, strlen(settings)); settings[0] = '\0'; ret = false; } storage_file_close(settings_file); storage_file_free(settings_file); furi_record_close(RECORD_STORAGE); if(strlen(settings) > 0) { Storage* fs_api = furi_record_open(RECORD_STORAGE); FileInfo layout_file_info; FS_Error file_check_err = storage_common_stat(fs_api, path, &layout_file_info); furi_record_close(RECORD_STORAGE); if(file_check_err != FSE_OK) { memzero(settings, strlen(settings)); settings[0] = '\0'; ret = false; } // if(layout_file_info.size != 256) { // memzero(settings, strlen(settings)); // settings[0] = '\0'; // } } return ret; } bool flipbip_has_file(const FlipBipFile file_type, const char* file_name, const bool remove) { bool ret = false; const char* path; char path_buf[FILE_MAX_PATH_LEN] = {0}; if(file_type == FlipBipFileKey) { path = FLIPBIP_KEY_PATH; } else if(file_type == FlipBipFileDat) { path = FLIPBIP_DAT_PATH; } else { strcpy(path_buf, FLIPBIP_APP_BASE_FOLDER); // 22 strcpy(path_buf + strlen(path_buf), "/"); strcpy(path_buf + strlen(path_buf), file_name); path = path_buf; } Storage* fs_api = furi_record_open(RECORD_STORAGE); if(remove) { ret = storage_simply_remove(fs_api, path); } else { ret = storage_file_exists(fs_api, path); } furi_record_close(RECORD_STORAGE); return ret; } bool flipbip_save_file( const char* settings, const FlipBipFile file_type, const char* file_name, const bool append) { bool ret = false; const char* path; const char* path_bak; char path_buf[FILE_MAX_PATH_LEN] = {0}; if(file_type == FlipBipFileKey) { path = FLIPBIP_KEY_PATH; path_bak = FLIPBIP_KEY_PATH_BAK; } else if(file_type == FlipBipFileDat) { path = FLIPBIP_DAT_PATH; path_bak = FLIPBIP_DAT_PATH_BAK; } else { strcpy(path_buf, FLIPBIP_APP_BASE_FOLDER); // 22 strcpy(path_buf + strlen(path_buf), "/"); strcpy(path_buf + strlen(path_buf), file_name); path = path_buf; path_bak = NULL; } int open_mode = FSOM_OPEN_ALWAYS; if(append) { open_mode = FSOM_OPEN_APPEND; } Storage* fs_api = furi_record_open(RECORD_STORAGE); // // if the key file exists, we don't want to overwrite it // if (key_file && storage_file_exists(fs_api, path)) { // furi_record_close(RECORD_STORAGE); // ret = true; // return ret; // } // try to create the folder storage_simply_mkdir(fs_api, FLIPBIP_APP_BASE_FOLDER); File* settings_file = storage_file_alloc(fs_api); if(storage_file_open(settings_file, path, FSAM_WRITE, open_mode)) { storage_file_write(settings_file, settings, strlen(settings)); storage_file_write(settings_file, "\n", 1); ret = true; } storage_file_close(settings_file); storage_file_free(settings_file); if(path_bak != NULL) { File* settings_file_bak = storage_file_alloc(fs_api); if(storage_file_open(settings_file_bak, path_bak, FSAM_WRITE, open_mode)) { storage_file_write(settings_file_bak, settings, strlen(settings)); storage_file_write(settings_file_bak, "\n", 1); } storage_file_close(settings_file_bak); storage_file_free(settings_file_bak); } furi_record_close(RECORD_STORAGE); return ret; } bool flipbip_save_qrfile( const char* qr_msg_prefix, const char* qr_msg_content, const char* file_name) { char qr_buf[FILE_MAX_QRFILE_CONTENT] = {0}; strcpy(qr_buf, TEXT_QRFILE); strcpy(qr_buf + strlen(qr_buf), qr_msg_prefix); strcpy(qr_buf + strlen(qr_buf), qr_msg_content); return flipbip_save_file(qr_buf, FlipBipFileOther, file_name, false); } bool flipbip_load_file_secure(char* settings) { const size_t dlen = FILE_HLEN + FILE_SLEN + 1; // allocate memory for key/data char* data = malloc(dlen); memzero(data, dlen); // load k2 from file if(!flipbip_load_file(data, dlen, FlipBipFileKey, NULL)) return false; // check header if(data[0] != FILE_HSTR[0] || data[1] != FILE_HSTR[1] || data[2] != FILE_HSTR[2] || data[3] != FILE_HSTR[3]) { memzero(data, dlen); free(data); return false; } // seek --> header data += FILE_HLEN; // prepare k1 uint8_t k1[64]; flipbip_xtob(FILE_K1, k1, strlen(FILE_K1) / 2); // load k2 from file buffer (secured by k1) flipbip_cipher(k1, strlen(FILE_K1) / 2, data, data, FILE_KLEN); uint8_t k2[128]; flipbip_xtob(data, k2, FILE_KLEN / 2); // zero k2 buffer memzero(data, FILE_KLEN); // seek <-- header data -= FILE_HLEN; // load data from file if(!flipbip_load_file(data, dlen, FlipBipFileDat, NULL)) return false; // check header if(data[0] != FILE_HSTR[0] || data[1] != FILE_HSTR[1] || data[2] != FILE_HSTR[2] || data[3] != FILE_HSTR[3]) { memzero(data, dlen); free(data); memzero(k1, strlen(FILE_K1) / 2); memzero(k2, FILE_KLEN / 2); return false; } // seek --> header data += FILE_HLEN; // load settings from file buffer (secured by k2) flipbip_cipher(k2, FILE_KLEN / 2, data, data, FILE_SLEN); flipbip_xtob(data, (unsigned char*)data, FILE_SLEN / 2); // copy to output strcpy(settings, data); // seek <-- header data -= FILE_HLEN; // clear memory memzero(data, dlen); free(data); memzero(k1, strlen(FILE_K1) / 2); memzero(k2, FILE_KLEN / 2); return true; } bool flipbip_save_file_secure(const char* settings) { const size_t dlen = FILE_HLEN + FILE_SLEN + 1; // cap settings to 256 bytes size_t len = strlen(settings); if(len > (FILE_SLEN / 2)) len = FILE_SLEN / 2; // allocate memory for key/data char* data = malloc(dlen); memzero(data, dlen); // write header strncpy(data, FILE_HSTR, FILE_HLEN); // seek --> header data += FILE_HLEN; // prepare k1 uint8_t k1[64]; flipbip_xtob(FILE_K1, k1, strlen(FILE_K1) / 2); // generate k2 uint8_t k2[128]; random_buffer(k2, FILE_KLEN / 2); // write k2 to file buffer (secured by k1) flipbip_btox(k2, FILE_KLEN / 2, data); flipbip_cipher(k1, strlen(FILE_K1) / 2, data, data, FILE_KLEN); // seek <-- header data -= FILE_HLEN; // save k2 to file flipbip_save_file(data, FlipBipFileKey, NULL, false); // seek --> header data += FILE_HLEN; // zero k2 memory memzero(data, FILE_KLEN); // write settings to file buffer (secured by k2) flipbip_btox((uint8_t*)settings, len, data); flipbip_cipher(k2, FILE_KLEN / 2, data, data, FILE_SLEN); // seek <-- header data -= FILE_HLEN; // save data to file flipbip_save_file(data, FlipBipFileDat, NULL, false); // clear memory memzero(data, dlen); free(data); memzero(k1, strlen(FILE_K1) / 2); memzero(k2, FILE_KLEN / 2); return true; }