Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ea0a922

Browse filesBrowse files
committed
file encryption/decryption support
1 parent 5989651 commit ea0a922
Copy full SHA for ea0a922

File tree

Expand file treeCollapse file tree

9 files changed

+297
-1
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+297
-1
lines changed

‎applications/debug/unit_tests/storage/storage_test.c

Copy file name to clipboardExpand all lines: applications/debug/unit_tests/storage/storage_test.c
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "../minunit.h"
22
#include <furi.h>
33
#include <storage/storage.h>
4+
#include <toolbox/stream/file_stream.h>
45

56
#define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test")
67
#define STORAGE_LOCKED_DIR STORAGE_INT_PATH_PREFIX
@@ -309,9 +310,37 @@ MU_TEST_SUITE(storage_rename) {
309310
furi_record_close(RECORD_STORAGE);
310311
}
311312

313+
MU_TEST(storage_encrypt_file) {
314+
Storage* storage = furi_record_open(RECORD_STORAGE);
315+
File* file;
316+
const char* path = EXT_PATH("enc_file");
317+
const uint8_t key_slot = 0;
318+
319+
file = storage_file_alloc(storage);
320+
mu_check(storage_file_open(file, path, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
321+
322+
const char* content = "Lorem ipsum dolor sit amet, cons";
323+
mu_check(storage_file_write(file, content, 32) == 32);
324+
storage_file_free(file);
325+
326+
mu_assert_int_eq(FSE_OK, storage_file_encrypt(storage, path, key_slot));
327+
mu_check(storage_file_is_encrypted(storage, path));
328+
329+
furi_record_close(RECORD_STORAGE);
330+
}
331+
332+
MU_TEST_SUITE(storage_encrypt_decrypt) {
333+
MU_RUN_TEST(storage_encrypt_file);
334+
335+
Storage* storage = furi_record_open(RECORD_STORAGE);
336+
storage_dir_remove(storage, EXT_PATH("enc_file"));
337+
furi_record_close(RECORD_STORAGE);
338+
}
339+
312340
int run_minunit_test_storage() {
313341
MU_RUN_SUITE(storage_file);
314342
MU_RUN_SUITE(storage_dir);
315343
MU_RUN_SUITE(storage_rename);
344+
MU_RUN_SUITE(storage_encrypt_decrypt);
316345
return MU_EXIT_CODE;
317346
}

‎applications/services/storage/filesystem_api.c

Copy file name to clipboardExpand all lines: applications/services/storage/filesystem_api.c
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ const char* filesystem_api_error_get_desc(FS_Error error_id) {
3333
case(FSE_ALREADY_OPEN):
3434
result = "file is already open";
3535
break;
36+
case(FSE_NO_SPACE):
37+
result = "no free space";
38+
break;
3639
}
3740
return result;
3841
}

‎applications/services/storage/filesystem_api_defines.h

Copy file name to clipboardExpand all lines: applications/services/storage/filesystem_api_defines.h
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ typedef enum {
3333
FSE_INTERNAL, /**< Internal error */
3434
FSE_NOT_IMPLEMENTED, /**< Functon not implemented */
3535
FSE_ALREADY_OPEN, /**< File/Dir already opened */
36+
FSE_NO_SPACE, /**< No free space available */
3637
} FS_Error;
3738

3839
/** FileInfo flags */

‎applications/services/storage/filesystem_api_internal.h

Copy file name to clipboardExpand all lines: applications/services/storage/filesystem_api_internal.h
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,27 @@
66
extern "C" {
77
#endif
88

9+
#define ENCRYPTION_IV_SIZE 16
10+
#define ENCRYPTION_EXT ".enc"
11+
12+
/** Magic bytes to detect if file is encrypted.
13+
* Encrypted file bytes layout is as follows:
14+
* --------------- ----------------- ---------------- -----------------------
15+
* | 7 bytes magic | 1 byte key slot | 16 byte vector | actual encrypted data |
16+
* --------------- ----------------- ---------------- -----------------------
17+
*/
18+
static const uint8_t encryption_magic_bytes[7] = {0x46, 0x45, 0x46, 0x2e, 0x41, 0x45, 0x53};
19+
static const size_t encryption_magic_size =
20+
sizeof(encryption_magic_bytes) / sizeof(encryption_magic_bytes[0]);
21+
static const size_t encryption_header_size =
22+
encryption_magic_size + sizeof(uint8_t) + ENCRYPTION_IV_SIZE;
23+
24+
/** Structure that holds file encryption info */
25+
typedef struct FileEncryption {
26+
bool decrypted; /**< Current encryption state */
27+
uint8_t key_slot; /**< Slot number of encryption key */
28+
} FileEncryption;
29+
930
/** File type */
1031
typedef enum {
1132
FileTypeClosed, /**< Closed file */
@@ -17,9 +38,11 @@ typedef enum {
1738
struct File {
1839
uint32_t file_id; /**< File ID for internal references */
1940
FileType type;
41+
const char* path; /**< Actual path of opened file */
2042
FS_Error error_id; /**< Standart API error from FS_Error enum */
2143
int32_t internal_error_id; /**< Internal API error value */
2244
void* storage;
45+
FileEncryption* encryption;
2346
};
2447

2548
/** File api structure

‎applications/services/storage/storage.h

Copy file name to clipboardExpand all lines: applications/services/storage/storage.h
+33Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,39 @@ bool storage_file_sync(File* file);
135135
*/
136136
bool storage_file_eof(File* file);
137137

138+
/** Checks that file at given path is encrypted
139+
* @param storage
140+
* @param path path to file.
141+
* @return bool success flag
142+
*/
143+
bool storage_file_is_encrypted(Storage* storage, const char* path);
144+
145+
/** Checks that file is decrypted at the moment
146+
* @param file pointer to file object.
147+
* @return bool success flag
148+
*/
149+
bool storage_file_is_decrypted(File* file);
150+
151+
/** Reports if encryption is enabled for this file
152+
* @param file pointer to file object.
153+
* @return bool success flag
154+
*/
155+
bool storage_file_secured(File* file);
156+
157+
/** Decrypts previously encrypted file
158+
* @param file pointer to file object.
159+
* @return FS_Error operation result
160+
*/
161+
FS_Error storage_file_decrypt(File* file);
162+
163+
/** Encrypts file using key from given secure enclave slot
164+
* @param storage
165+
* @param path path to file.
166+
* @param key_slot slot of key in secure enclave.
167+
* @return FS_Error operation result
168+
*/
169+
FS_Error storage_file_encrypt(Storage* storage, const char* path, uint8_t key_slot);
170+
138171
/**
139172
* @brief Check that file exists
140173
*

‎applications/services/storage/storage_external_api.c

Copy file name to clipboardExpand all lines: applications/services/storage/storage_external_api.c
+44Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,29 @@ bool storage_file_exists(Storage* storage, const char* path) {
259259
return exist;
260260
}
261261

262+
FS_Error storage_file_decrypt(File* file) {
263+
if(storage_file_is_decrypted(file)) {
264+
return FSE_OK;
265+
}
266+
267+
S_FILE_API_PROLOGUE;
268+
S_API_PROLOGUE;
269+
S_API_DATA_FILE;
270+
S_API_MESSAGE(StorageCommandFileDecrypt);
271+
S_API_EPILOGUE;
272+
return S_RETURN_ERROR;
273+
}
274+
275+
FS_Error storage_file_encrypt(Storage* storage, const char* path, uint8_t key_slot) {
276+
S_API_PROLOGUE;
277+
278+
SAData data = {.encryption = {.path = path, .key_slot = key_slot}};
279+
280+
S_API_MESSAGE(StorageCommandFileEncrypt);
281+
S_API_EPILOGUE;
282+
return S_RETURN_ERROR;
283+
}
284+
262285
/****************** DIR ******************/
263286

264287
static bool storage_dir_open_internal(File* file, const char* path) {
@@ -714,6 +737,26 @@ bool storage_file_is_dir(File* file) {
714737
return (file->type == FileTypeOpenDir);
715738
}
716739

740+
bool storage_file_is_encrypted(Storage* storage, const char* path) {
741+
Stream* fstream = file_stream_alloc(storage);
742+
if(!file_stream_open(fstream, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
743+
stream_free(fstream);
744+
return false;
745+
};
746+
uint8_t magic_buf[encryption_magic_size];
747+
stream_read(fstream, magic_buf, encryption_magic_size);
748+
stream_free(fstream);
749+
return memcmp(&encryption_magic_bytes, &magic_buf, encryption_magic_size) == 0;
750+
}
751+
752+
bool storage_file_is_decrypted(File* file) {
753+
return file->encryption && file->encryption->decrypted;
754+
}
755+
756+
bool storage_file_secured(File* file) {
757+
return file->encryption;
758+
}
759+
717760
void storage_file_free(File* file) {
718761
if(storage_file_is_open(file)) {
719762
if(storage_file_is_dir(file)) {
@@ -724,6 +767,7 @@ void storage_file_free(File* file) {
724767
}
725768

726769
FURI_LOG_T(TAG, "File/Dir %p free", (void*)((uint32_t)file - SRAM_BASE));
770+
free(file->encryption);
727771
free(file);
728772
}
729773

‎applications/services/storage/storage_message.h

Copy file name to clipboardExpand all lines: applications/services/storage/storage_message.h
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ typedef struct {
7070
File* file;
7171
} SADataFile;
7272

73+
typedef struct {
74+
const char* path;
75+
const uint8_t key_slot;
76+
} SADataEncryption;
77+
7378
typedef struct {
7479
SDInfo* info;
7580
} SAInfo;
@@ -91,6 +96,7 @@ typedef union {
9196

9297
SADataFile file;
9398
SADataPath path;
99+
SADataEncryption encryption;
94100

95101
SAInfo sdinfo;
96102
} SAData;
@@ -114,6 +120,8 @@ typedef enum {
114120
StorageCommandFileSize,
115121
StorageCommandFileSync,
116122
StorageCommandFileEof,
123+
StorageCommandFileEncrypt,
124+
StorageCommandFileDecrypt,
117125
StorageCommandDirOpen,
118126
StorageCommandDirClose,
119127
StorageCommandDirRead,

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.