646 lines
18 KiB
C
646 lines
18 KiB
C
#include <stdint.h>
|
|
#include <string.h>
|
|
#include "usecfs.h"
|
|
#include "usecfs_dev.h"
|
|
|
|
|
|
#ifndef NULL
|
|
# define NULL (void *)0
|
|
#endif
|
|
|
|
#define NO_BLOCK (0xFFFFFFFFUL)
|
|
#ifndef BLOCKDEV_OPEN_ARGS
|
|
# define BLOCKDEV_OPEN_ARGS (NULL)
|
|
#endif
|
|
|
|
#define MAX_BLOCKS_0 ((BLOCK_SIZE - MAX_FILENAME) / 4) - 3 /* accounts for 3 32bit fields + FILENAME */
|
|
#define MAX_BLOCKS_N ((BLOCK_SIZE - MAX_FILENAME) / 4) - 1 /* overhead is only 'extra' fields */
|
|
#define MAX_INLINE_SIZE ((MAX_BLOCKS_0 - 1) * 4) /* Max data size for self-contained block */
|
|
#define INLINE_PAYLOAD(x) ((uint8_t *)(&x->blk[1])) /* Macro to access INLINE paylaod */
|
|
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
#include <wolfssl/options.h>
|
|
#include <wolfssl/wolfcrypt/sha256.h>
|
|
#ifdef CRYPTO
|
|
#define CRYPTO_BLOCK_SIZE 16
|
|
|
|
uint8_t crypto_tmp[CRYPTO_BLOCK_SIZE];
|
|
uint8_t crypto_iv[CRYPTO_BLOCK_SIZE];
|
|
|
|
#include <wolfssl/wolfcrypt/chacha.h>
|
|
#include <wolfssl/wolfcrypt/pwdbased.h>
|
|
|
|
static ChaCha chacha;
|
|
|
|
ChaCha *chacha_secret = &chacha;
|
|
|
|
#define CRYPTO_KEY_SIZE 32
|
|
#endif
|
|
|
|
#define HASH_LEN 32
|
|
#define MAGIC 0x5AFED15C
|
|
|
|
static uint8_t cache[BLOCK_SIZE];
|
|
static uint8_t inline_buffer_copy[MAX_INLINE_SIZE];
|
|
|
|
|
|
struct __attribute__((packed)) extra {
|
|
uint32_t extra;
|
|
uint32_t blk[(BLOCK_SIZE / 4) - 1];
|
|
};
|
|
|
|
struct __attribute__((packed)) inode {
|
|
uint32_t extra;
|
|
uint32_t blk[((BLOCK_SIZE - MAX_FILENAME) / 4) - 3];
|
|
uint32_t size;
|
|
uint32_t nextfile;
|
|
char filename[MAX_FILENAME];
|
|
};
|
|
|
|
struct __attribute__((packed)) root_block {
|
|
uint32_t magic;
|
|
uint32_t blk[((BLOCK_SIZE - MAX_FILENAME) / 4) - 3];
|
|
uint32_t fs_size; /* unused */
|
|
uint32_t nextfile;
|
|
uint8_t uuid[UUID_LEN];
|
|
uint8_t hash[HASH_LEN];
|
|
};
|
|
|
|
|
|
/* One-sector cache, single entry point for read/write
|
|
* on blocks
|
|
*/
|
|
static uint32_t cached_block = NO_BLOCK;
|
|
void *blockdev = NULL;
|
|
|
|
static int is_block_empty(void)
|
|
{
|
|
uint32_t *w = (uint32_t *)cache;
|
|
int i;
|
|
for(i = 0; i < (BLOCK_SIZE / sizeof(uint32_t)); i++) {
|
|
if (w[i] != NO_BLOCK)
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static void cache_commit(void)
|
|
{
|
|
if (cached_block == NO_BLOCK)
|
|
return;
|
|
#ifdef CRYPTO
|
|
if (!is_block_empty()) {
|
|
uint32_t i;
|
|
memset(crypto_iv, 0, CRYPTO_BLOCK_SIZE);
|
|
for (i = 0; i < BLOCK_SIZE / CRYPTO_BLOCK_SIZE; i++) {
|
|
memcpy(&crypto_iv[0], &cached_block, sizeof(uint32_t));
|
|
memcpy(&crypto_iv[4], &i, sizeof(uint32_t));
|
|
memcpy(crypto_tmp, cache + (i * CRYPTO_BLOCK_SIZE), CRYPTO_BLOCK_SIZE);
|
|
wc_Chacha_SetIV(&chacha, crypto_iv, CRYPTO_BLOCK_SIZE);
|
|
wc_Chacha_Process(&chacha, cache + i * CRYPTO_BLOCK_SIZE, crypto_tmp, CRYPTO_BLOCK_SIZE);
|
|
}
|
|
}
|
|
#endif
|
|
block_write(blockdev, cache, cached_block);
|
|
cached_block = NO_BLOCK;
|
|
}
|
|
|
|
static void cache_load(uint32_t blk)
|
|
{
|
|
if (cached_block == blk)
|
|
return;
|
|
if (cached_block != NO_BLOCK)
|
|
cache_commit();
|
|
if (block_read(blockdev, cache, blk) == BLOCK_SIZE) {
|
|
cached_block = blk;
|
|
#ifdef CRYPTO
|
|
if (!is_block_empty()) {
|
|
uint32_t i;
|
|
memset(crypto_iv, 0, CRYPTO_BLOCK_SIZE);
|
|
for (i = 0; i < BLOCK_SIZE / CRYPTO_BLOCK_SIZE; i++) {
|
|
memcpy(&crypto_iv[0], &blk, sizeof(uint32_t));
|
|
memcpy(&crypto_iv[4], &i, sizeof(uint32_t));
|
|
memcpy(crypto_tmp, cache + (i * CRYPTO_BLOCK_SIZE), CRYPTO_BLOCK_SIZE);
|
|
wc_Chacha_SetIV(&chacha, crypto_iv, CRYPTO_BLOCK_SIZE);
|
|
wc_Chacha_Process(&chacha, cache + i * CRYPTO_BLOCK_SIZE, crypto_tmp, CRYPTO_BLOCK_SIZE);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static uint32_t get_file(const char *filename)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
uint32_t blk = 0;
|
|
cache_load(blk);
|
|
while (1) {
|
|
if (strncmp(filename, ci->filename, MAX_FILENAME - 1) == 0)
|
|
return blk;
|
|
if (ci->nextfile != NO_BLOCK) {
|
|
blk = ci->nextfile;
|
|
cache_load(blk);
|
|
} else
|
|
return NO_BLOCK;
|
|
}
|
|
return NO_BLOCK; /* Never reached */
|
|
}
|
|
|
|
static uint32_t get_free_block(uint32_t *fs_tail)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
struct extra *ce = (struct extra *)cache;
|
|
uint32_t first_free = 1;
|
|
uint32_t cur_inode_0 = 0;
|
|
int i;
|
|
cache_load(0);
|
|
if (ci->nextfile == NO_BLOCK) {
|
|
if (fs_tail)
|
|
*fs_tail = 0;
|
|
return 1;
|
|
}
|
|
cur_inode_0 = ci->nextfile;
|
|
cache_load(cur_inode_0);
|
|
while (1) {
|
|
for (i = 0; i < MAX_BLOCKS_0; i++)
|
|
{
|
|
if (ci->blk[i] == NO_BLOCK)
|
|
break;
|
|
if (first_free == ci->blk[i])
|
|
first_free++;
|
|
}
|
|
if (ci->extra != NO_BLOCK)
|
|
{
|
|
cache_load(ci->extra);
|
|
while (1) {
|
|
for (i = 0; i < MAX_BLOCKS_N; i++)
|
|
{
|
|
if (ce->blk[i] == NO_BLOCK)
|
|
break;
|
|
if (first_free == ce->blk[i])
|
|
first_free++;
|
|
}
|
|
if (ce->extra == NO_BLOCK)
|
|
break;
|
|
cache_load(ce->extra);
|
|
}
|
|
cache_load(cur_inode_0);
|
|
}
|
|
if (ci->nextfile != NO_BLOCK) {
|
|
cur_inode_0 = ci->nextfile;
|
|
cache_load(cur_inode_0);
|
|
} else {
|
|
if (fs_tail)
|
|
*fs_tail = cur_inode_0;
|
|
return first_free;
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint32_t new_inode(void)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
uint32_t fs_tail = NO_BLOCK;
|
|
uint32_t new_block = get_free_block(&fs_tail);
|
|
if (new_block == NO_BLOCK || fs_tail == NO_BLOCK)
|
|
return NO_BLOCK;
|
|
|
|
cache_load(fs_tail);
|
|
ci->nextfile = new_block;
|
|
cache_load(new_block);
|
|
memset(cache, 0xFF, BLOCK_SIZE);
|
|
ci->nextfile = NO_BLOCK;
|
|
return new_block;
|
|
}
|
|
|
|
struct openfile {
|
|
uint32_t blk;
|
|
uint32_t off;
|
|
};
|
|
|
|
struct openfile OpenFiles[MAX_OPEN_FILES];
|
|
static int get_free_fd(void)
|
|
{
|
|
int i, free_fd = -1;
|
|
|
|
for (i = 0; i < MAX_OPEN_FILES; i++) {
|
|
if (OpenFiles[i].blk == NO_BLOCK) {
|
|
free_fd = i;
|
|
break;
|
|
}
|
|
}
|
|
return free_fd;
|
|
}
|
|
|
|
static uint32_t get_index_block(uint32_t inode0, uint32_t off)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
struct extra *ce = (struct extra *)cache;
|
|
uint32_t idx = 0;
|
|
cache_load(inode0);
|
|
idx = off / BLOCK_SIZE;
|
|
if (idx <= MAX_BLOCKS_0)
|
|
return inode0;
|
|
if (ci->extra == NO_BLOCK)
|
|
return NO_BLOCK;
|
|
inode0 = ci->extra;
|
|
cache_load(inode0);
|
|
idx -= MAX_BLOCKS_0;
|
|
while (idx >= MAX_BLOCKS_N) {
|
|
if (ce->extra == NO_BLOCK)
|
|
return NO_BLOCK;
|
|
inode0 = ce->extra;
|
|
cache_load(inode0);
|
|
idx -= MAX_BLOCKS_N;
|
|
}
|
|
return inode0;
|
|
}
|
|
|
|
static void set_block(uint32_t node0, uint32_t nodeN, uint32_t off)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
struct extra *ce = (struct extra *)cache;
|
|
uint32_t idx;
|
|
uint32_t idxblk;
|
|
idxblk = get_index_block(node0, off);
|
|
}
|
|
|
|
static void file_grow(uint32_t node0, uint32_t newsize)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
struct extra *ce = (struct extra *)cache;
|
|
uint32_t cur_idx, new_idx;
|
|
uint32_t cur_idx_block, new_idx_block;
|
|
uint32_t i;
|
|
cache_load(node0);
|
|
cur_idx = ci->size / BLOCK_SIZE;
|
|
new_idx = newsize / BLOCK_SIZE;
|
|
cur_idx_block = get_index_block(node0, ci->size);
|
|
new_idx_block = get_index_block(node0, newsize);
|
|
|
|
for (i = cur_idx; i < new_idx; i++) {
|
|
cur_idx_block = get_index_block(node0, i * BLOCK_SIZE);
|
|
if (cur_idx_block == NO_BLOCK)
|
|
return;
|
|
cache_load(cur_idx_block);
|
|
if (cur_idx_block == node0) {
|
|
uint32_t idx = i + 1;
|
|
if (idx == (MAX_BLOCKS_0)) {
|
|
uint32_t extra = get_free_block(NULL);
|
|
cache_load(extra);
|
|
memset(cache, 0xFF, BLOCK_SIZE);
|
|
cache_load(node0);
|
|
ci->extra = extra;
|
|
cache_load(extra);
|
|
idx = 0;
|
|
}
|
|
ci->blk[idx] = get_free_block(NULL);
|
|
} else {
|
|
uint32_t idx = ((i - MAX_BLOCKS_0) % MAX_BLOCKS_N) + 1;
|
|
if (idx == MAX_BLOCKS_N) {
|
|
uint32_t extra = get_free_block(NULL);
|
|
cache_load(extra);
|
|
memset(cache, 0xFF, BLOCK_SIZE);
|
|
cache_load(cur_idx_block);
|
|
ce->extra = extra;
|
|
cache_load(extra);
|
|
idx = 0;
|
|
}
|
|
ce->blk[idx] = get_free_block(NULL);
|
|
}
|
|
}
|
|
if (ci->size < newsize)
|
|
ci->size = newsize;
|
|
}
|
|
|
|
/* Public interface */
|
|
|
|
int usecfs_format(const uint8_t *uuid)
|
|
{
|
|
struct root_block *rb = (struct root_block *)cache;
|
|
wc_Sha256 sha;
|
|
cache_load(0);
|
|
memset(cache, 0xFF, BLOCK_SIZE);
|
|
rb->magic = MAGIC;
|
|
rb->blk[0] = 0;
|
|
memcpy(rb->uuid, uuid, UUID_LEN);
|
|
wc_InitSha256(&sha);
|
|
wc_Sha256Update(&sha, uuid, UUID_LEN);
|
|
wc_Sha256Final(&sha, rb->hash);
|
|
cache_commit();
|
|
return 0;
|
|
}
|
|
|
|
int usecfs_mount(uint8_t *uuid)
|
|
{
|
|
struct root_block *rb = (struct root_block *)cache;
|
|
wc_Sha256 sha;
|
|
uint8_t hash[HASH_LEN];
|
|
cache_load(0);
|
|
if (rb->magic != MAGIC)
|
|
return -1;
|
|
wc_InitSha256(&sha);
|
|
wc_Sha256Update(&sha, rb->uuid, UUID_LEN);
|
|
wc_Sha256Final(&sha, hash);
|
|
if (memcmp(hash, rb->hash, HASH_LEN) != 0)
|
|
return -1;
|
|
if (uuid)
|
|
memcpy(uuid, rb->uuid, UUID_LEN);
|
|
return 0;
|
|
}
|
|
|
|
int usecfs_read(int fd, void *data, uint32_t len)
|
|
{
|
|
int r = 0;
|
|
uint32_t node0 = OpenFiles[fd].blk;
|
|
uint32_t *off = &OpenFiles[fd].off;
|
|
struct inode *ci = (struct inode *)cache;
|
|
if (node0 == NO_BLOCK)
|
|
return -1;
|
|
cache_load(node0);
|
|
if ((ci->size - *off) < len)
|
|
len = ci->size - *off;
|
|
if (ci->blk[0] == node0) {
|
|
/* file is INLINE */
|
|
memcpy(data, INLINE_PAYLOAD(ci), len);
|
|
*off += len;
|
|
return len;
|
|
}
|
|
while (r < len) {
|
|
int idx = *off / BLOCK_SIZE;
|
|
uint32_t idx_block;
|
|
uint32_t off_within_block;
|
|
uint32_t len_within_block;
|
|
|
|
/* Find the index block for the offset */
|
|
idx_block = get_index_block(node0, *off);
|
|
if (idx_block == NO_BLOCK)
|
|
return -1;
|
|
cache_load(idx_block);
|
|
if (ci->blk[idx] == NO_BLOCK)
|
|
return -1;
|
|
cache_load(ci->blk[idx]);
|
|
|
|
/* Find the offset/len within this block */
|
|
off_within_block = *off % BLOCK_SIZE;
|
|
len_within_block = BLOCK_SIZE - off_within_block;
|
|
if (len_within_block > (len - r))
|
|
len_within_block = (len - r);
|
|
|
|
/* Copy data from cache, increase counters */
|
|
memcpy(data + r, cache + off_within_block, len_within_block);
|
|
r += len_within_block;
|
|
*off += len_within_block;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
int usecfs_write(int fd, const void *data, uint32_t len)
|
|
{
|
|
int w = 0;
|
|
uint32_t node0 = OpenFiles[fd].blk;
|
|
uint32_t *off = &OpenFiles[fd].off;
|
|
struct inode *ci = (struct inode *)cache;
|
|
uint32_t blkn;
|
|
if (node0 == NO_BLOCK)
|
|
return -1;
|
|
cache_load(node0);
|
|
if (ci->size + *off <= MAX_INLINE_SIZE) {
|
|
if (ci->size + *off + len <= MAX_INLINE_SIZE) {
|
|
/* file can still be inline */
|
|
memcpy(INLINE_PAYLOAD(ci) + *off, data, len);
|
|
*off += len;
|
|
if (*off > ci->size)
|
|
ci->size = *off;
|
|
cache_commit();
|
|
return len;
|
|
} else {
|
|
/* Special case: migrating data to new block */
|
|
memcpy(inline_buffer_copy, INLINE_PAYLOAD(ci), MAX_INLINE_SIZE);
|
|
blkn = get_free_block(NULL);
|
|
memcpy(cache, inline_buffer_copy, MAX_INLINE_SIZE);
|
|
cache_load(node0);
|
|
ci->blk[0] = blkn;
|
|
}
|
|
}
|
|
if (ci->size < *off + len)
|
|
file_grow(node0, *off + len);
|
|
|
|
while (w < len) {
|
|
uint32_t off_within_block;
|
|
uint32_t len_within_block;
|
|
int idx = *off / BLOCK_SIZE;
|
|
uint32_t idx_block;
|
|
|
|
idx_block = get_index_block(node0, *off);
|
|
if (idx_block == NO_BLOCK)
|
|
return -1;
|
|
|
|
cache_load(idx_block);
|
|
off_within_block = *off % BLOCK_SIZE;
|
|
len_within_block = BLOCK_SIZE - off_within_block;
|
|
if (len_within_block > (len - w))
|
|
len_within_block = (len - w);
|
|
if (ci->blk[idx] == NO_BLOCK)
|
|
return -1;
|
|
cache_load(ci->blk[idx]);
|
|
memcpy(cache + off_within_block, data + w, len_within_block);
|
|
w += len_within_block;
|
|
*off += len_within_block;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
int usecfs_seek(int fd, int offset, int whence)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
if (OpenFiles[fd].blk == NO_BLOCK)
|
|
return -1;
|
|
cache_load(OpenFiles[fd].blk);
|
|
switch(whence) {
|
|
case 0: /* SEEK_SET */
|
|
if (offset < 0)
|
|
return -1;
|
|
OpenFiles[fd].off = offset;
|
|
break;
|
|
case 1: /* SEEK_CUR */
|
|
if ((OpenFiles[fd].off - offset) < 0)
|
|
OpenFiles[fd].off = 0;
|
|
else
|
|
OpenFiles[fd].off += offset;
|
|
break;
|
|
case 2: /* SEEK_END */
|
|
OpenFiles[fd].off = ci->size + offset;
|
|
break;
|
|
default:
|
|
return -1;
|
|
} /* switch(whence) */
|
|
if (OpenFiles[fd].off > ci->size)
|
|
file_grow(OpenFiles[fd].blk, OpenFiles[fd].off);
|
|
return OpenFiles[fd].off;
|
|
}
|
|
|
|
int usecfs_open(const char *name)
|
|
{
|
|
int free_fd;
|
|
free_fd = get_free_fd();
|
|
if (free_fd < 0)
|
|
return -1;
|
|
OpenFiles[free_fd].blk = get_file(name);
|
|
if (OpenFiles[free_fd].blk == NO_BLOCK)
|
|
return -1;
|
|
OpenFiles[free_fd].off = 0;
|
|
return free_fd;
|
|
}
|
|
|
|
int usecfs_creat(const char *name)
|
|
{
|
|
int free_fd;
|
|
int i;
|
|
uint32_t newnode;
|
|
struct inode *ci = (struct inode *)cache;
|
|
free_fd = get_free_fd();
|
|
if (free_fd < 0)
|
|
return -1;
|
|
if (get_file(name) != NO_BLOCK)
|
|
return -1;
|
|
newnode = new_inode();
|
|
if (newnode == NO_BLOCK)
|
|
return -1;
|
|
OpenFiles[free_fd].blk = newnode;
|
|
|
|
/* Initialize inode (already in cache from new_inode()) */
|
|
ci->size = 0; /* newly created file is zero bytes long */
|
|
memset(ci->filename, 0, MAX_FILENAME);
|
|
for (i = 0; (i < strlen(name)) && (i < MAX_FILENAME - 1); i++)
|
|
ci->filename[i] = name[i];
|
|
ci->blk[0] = newnode; /* self-reference, start as INLINE */
|
|
for (i = 1; i < MAX_BLOCKS_0; i++)
|
|
ci->blk[i] = NO_BLOCK;
|
|
OpenFiles[free_fd].off = 0;
|
|
cache_commit();
|
|
return free_fd;
|
|
}
|
|
|
|
int usecfs_truncate(int fd, uint32_t newsize)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
struct extra *ce = (struct extra *)cache;
|
|
uint32_t idx, new_idx;
|
|
uint32_t last_block_idx;
|
|
uint32_t idx_block, new_idx_block;
|
|
uint32_t node0 = OpenFiles[fd].blk;
|
|
uint32_t idx_off;
|
|
uint32_t i;
|
|
if (node0 == NO_BLOCK)
|
|
return -1;
|
|
cache_load(OpenFiles[fd].blk);
|
|
if (ci->size <= newsize)
|
|
return -1;
|
|
idx = ci->size / BLOCK_SIZE;
|
|
new_idx = newsize / BLOCK_SIZE;
|
|
if (ci->size <= (BLOCK_SIZE * MAX_BLOCKS_0) || /* File is inlined, or */
|
|
(idx == new_idx) ) /* number of blocks is unchanged? */
|
|
{
|
|
ci->size = newsize;
|
|
return 0;
|
|
}
|
|
if ((ci->size > MAX_INLINE_SIZE) && (newsize <= MAX_INLINE_SIZE))
|
|
{
|
|
/* Special case: file was big, now it's inlined. */
|
|
cache_load(ci->blk[0]);
|
|
memcpy(inline_buffer_copy, cache, newsize);
|
|
cache_load(node0);
|
|
memcpy(INLINE_PAYLOAD(ci), inline_buffer_copy, newsize);
|
|
ci->blk[0] = node0; /* establish self-reference */
|
|
for (i = 1; i < MAX_BLOCKS_0; i++)
|
|
ci->blk[i] = NO_BLOCK;
|
|
ci->size = newsize;
|
|
return 0;
|
|
}
|
|
idx_block = get_index_block(node0, ci->size);
|
|
new_idx_block = get_index_block(node0, newsize);
|
|
cache_load(new_idx_block);
|
|
if (idx_block != new_idx_block)
|
|
ci->extra = NO_BLOCK;
|
|
if (idx_block <= MAX_BLOCKS_0) {
|
|
idx_off = new_idx_block;
|
|
for (i = idx_off; i < MAX_BLOCKS_N; i++)
|
|
ce->blk[i] = NO_BLOCK;
|
|
} else {
|
|
idx_off = (new_idx_block - MAX_BLOCKS_0) % MAX_BLOCKS_N;
|
|
while (idx_off > MAX_BLOCKS_N)
|
|
idx_off -= MAX_BLOCKS_N;
|
|
for (i = idx_off; i < MAX_BLOCKS_N; i++)
|
|
ce->blk[i] = NO_BLOCK;
|
|
}
|
|
ci->size = newsize;
|
|
return 0;
|
|
}
|
|
|
|
int usecfs_unlink(const char *filename)
|
|
{
|
|
struct inode *ci = (struct inode *)cache;
|
|
uint32_t blk = 1;
|
|
uint32_t blk_prev = 0;
|
|
uint32_t blk_next;
|
|
cache_load(blk);
|
|
while (1) {
|
|
if (strncmp(filename, ci->filename, MAX_FILENAME - 1) == 0)
|
|
{
|
|
blk_next = ci->nextfile;
|
|
cache_load(blk_prev);
|
|
ci->nextfile = blk_next;
|
|
return 0;
|
|
}
|
|
if (ci->nextfile != NO_BLOCK) {
|
|
blk_prev = blk;
|
|
blk = ci->nextfile;
|
|
cache_load(blk);
|
|
} else
|
|
return -1;
|
|
}
|
|
return -1; /* Never reached */
|
|
}
|
|
|
|
int usecfs_close(int fd)
|
|
{
|
|
if (OpenFiles[fd].blk != NO_BLOCK) {
|
|
cache_commit();
|
|
OpenFiles[fd].blk = NO_BLOCK;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define SALT_LEN 32
|
|
const uint8_t password_salt[SALT_LEN] = {
|
|
0xe7, 0xa1, 0x9c, 0xb0, 0x48, 0xa8, 0x30, 0xf9, 0x37, 0xda, 0x8e, 0xde,
|
|
0xff, 0xb2, 0x62, 0x03, 0x24, 0x55, 0xb8, 0x8b, 0x7b, 0x18, 0x68, 0x57,
|
|
0x7d, 0x35, 0xbe, 0xbd, 0xf6, 0x0e, 0xc1, 0x2c
|
|
};
|
|
|
|
static uint8_t chacha_key[CRYPTO_KEY_SIZE];
|
|
int usecfs_getkey(void)
|
|
{
|
|
return chacha_key;
|
|
}
|
|
|
|
int usecfs_init(const char *password, int format, uint8_t *uuid)
|
|
{
|
|
blockdev = block_open(BLOCKDEV_OPEN_ARGS);
|
|
if (!blockdev)
|
|
return -1;
|
|
memset(OpenFiles, 0xFF, MAX_OPEN_FILES * sizeof(struct openfile));
|
|
{
|
|
int ret = 0;
|
|
ret = wc_PBKDF2(chacha_key, password, strlen(password), password_salt, SALT_LEN, 2048, CRYPTO_KEY_SIZE, SHA256);
|
|
wc_Chacha_SetKey(&chacha, chacha_key, CRYPTO_KEY_SIZE);
|
|
}
|
|
if (format) {
|
|
if (!uuid)
|
|
return -1;
|
|
else
|
|
return usecfs_format(uuid);
|
|
} else
|
|
return usecfs_mount(uuid);
|
|
}
|