Added USB-MSC
This commit is contained in:
parent
eb1a572eff
commit
c958c4becb
15 changed files with 1273 additions and 34 deletions
16
Makefile
16
Makefile
|
@ -1,15 +1,15 @@
|
|||
CROSS_COMPILE:=arm-none-eabi-
|
||||
CC:=$(CROSS_COMPILE)gcc
|
||||
LD:=$(CROSS_COMPILE)gcc
|
||||
USECFS:=$(HOME)/src/usecfs
|
||||
WOLFSSL:=$(HOME)/src/wolfssl
|
||||
|
||||
OBJS:=startup.o main.o system.o usecfs_dev_spi.o $(USECFS)/src/usecfs.o mem.o led.o \
|
||||
OBJS:=startup.o main.o system.o usecfs_dev_spi.o usecfs.o mem.o led.o \
|
||||
i2c.o display.o font_twisted.o spi.o spi_flash.o button.o systick.o newlib.o uart.o ui.o \
|
||||
sdcard.o random.o
|
||||
sdcard.o random.o usb.o mutex.o
|
||||
OBJS+= \
|
||||
$(WOLFSSL)/wolfcrypt/src/sha256.o \
|
||||
$(WOLFSSL)/wolfcrypt/src/chacha.o \
|
||||
$(WOLFSSL)/wolfcrypt/src/aes.o \
|
||||
$(WOLFSSL)/wolfcrypt/src/pwdbased.o \
|
||||
$(WOLFSSL)/wolfcrypt/src/hash.o \
|
||||
$(WOLFSSL)/wolfcrypt/src/hmac.o \
|
||||
|
@ -30,13 +30,14 @@ LSCRIPT:=target.ld
|
|||
|
||||
OBJCOPY:=$(CROSS_COMPILE)objcopy
|
||||
|
||||
CFLAGS:=-mcpu=cortex-m3 -mthumb -Wall -Wno-main -Wstack-usage=200 -ffreestanding -Wno-unused -DBLOCK_SIZE=4096 -I$(USECFS)/src -I. -I$(WOLFSSL) -Ilib/unicore-mx/include
|
||||
CFLAGS:=-mcpu=cortex-m3 -mthumb -Wall -Wno-main -Wstack-usage=200 -ffreestanding -Wno-unused -DBLOCK_SIZE=4096 -I. -I$(WOLFSSL) -Ilib/unicore-mx/include
|
||||
CFLAGS+=-specs=nano.specs -lc -lg
|
||||
CFLAGS+=$(UMXFLAGS)
|
||||
#CFLAGS+=-O2
|
||||
CFLAGS+=-g -ggdb3
|
||||
CFLAGS+=-O2
|
||||
#CFLAGS+=-g -ggdb3
|
||||
|
||||
CFLAGS+=-DWOLFSSL_USER_SETTINGS -DCRYPTO
|
||||
ASFLAGS:=$(CFLAGS)
|
||||
|
||||
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map -mcpu=cortex-m3 -mthumb -nostartfiles
|
||||
|
||||
|
@ -52,4 +53,5 @@ $(UMX):
|
|||
make -C lib/unicore-mx FP_FLAGS="-O3 -mfloat-abi=soft" TARGETS=stm32/f4
|
||||
|
||||
clean:
|
||||
rm -f image.bin image.elf *.o image.map $(WOLFSSL)/wolfcrypt/src/*.o $(USECFS)/src/*.o
|
||||
@rm -f image.bin image.elf *.o image.map $(WOLFSSL)/wolfcrypt/src/*.o $(USECFS)/src/*.o
|
||||
make -C lib/unicore-mx clean
|
||||
|
|
10
main.c
10
main.c
|
@ -17,6 +17,7 @@
|
|||
#include "ui.h"
|
||||
#include "sdcard.h"
|
||||
#include "button.h"
|
||||
#include "usb.h"
|
||||
extern uint32_t cpu_freq;
|
||||
|
||||
#define BLINK_INTERVAL 500
|
||||
|
@ -74,6 +75,10 @@ static void bootlevel_1(void)
|
|||
led_on(YELLOW_LED);
|
||||
sdcard_detected = 1;
|
||||
}
|
||||
|
||||
printf("Activating USB mass storage device\r\n");
|
||||
|
||||
printf("Activating I2C bus\r\n");
|
||||
|
||||
i2c_display_init();
|
||||
printf("Display initialized.\r\n");
|
||||
|
@ -89,10 +94,6 @@ static void bootlevel_1(void)
|
|||
void process_button(uint16_t press, int hold)
|
||||
{
|
||||
char c = bu2c(press);
|
||||
if (!hold)
|
||||
printf("Pressed '%c'.\r\n", c);
|
||||
else
|
||||
printf("Held '%c'.\r\n", c);
|
||||
ui_button_press(press);
|
||||
}
|
||||
|
||||
|
@ -127,6 +128,7 @@ int main(void) {
|
|||
|
||||
do {
|
||||
WFI();
|
||||
usb_poll();
|
||||
ret = button_poll(process_button);
|
||||
if (jiffies - poll_time > hb_pulse) {
|
||||
if (hb) {
|
||||
|
|
47
mutex.S
Normal file
47
mutex.S
Normal file
|
@ -0,0 +1,47 @@
|
|||
|
||||
.syntax unified
|
||||
|
||||
/* Lock function.
|
||||
* On success, return 0.
|
||||
* On failure, return -1 (Locked, try again later).
|
||||
*/
|
||||
|
||||
.global _mutex_lock
|
||||
_mutex_lock:
|
||||
LDREX r1, [r0]
|
||||
CMP r1, #0 // Test if mutex holds the value 0
|
||||
BEQ _mutex_lock_fail // If it does, return -1
|
||||
SUBS r1, #1 // If not, decrement temporary copy
|
||||
STREX r2, r1, [r0] // Attempt Store-Exclusive
|
||||
CMP r2, #0 // Check if Store-Exclusive succeeded
|
||||
BNE _mutex_lock // If Store-Exclusive failed, retry from start
|
||||
DMB // Required before accessing protected resource
|
||||
MOVS r0, #0 // Successfully locked.
|
||||
BX lr
|
||||
_mutex_lock_fail:
|
||||
DMB
|
||||
MOV r0, #-1 // Already locked!
|
||||
BX lr
|
||||
|
||||
/* Unlock mutex.
|
||||
* On success, return 0.
|
||||
* On failure, return -1 (Already unlocked!).
|
||||
*/
|
||||
|
||||
.global _mutex_unlock
|
||||
_mutex_unlock:
|
||||
LDREX r1, [r0]
|
||||
CMP r1, #0 // Test if mutex holds the value 0
|
||||
BNE _mutex_unlock_fail // If it does not, it's already unlocked!
|
||||
ADDS r1, #1 // Increment temporary copy
|
||||
STREX r2, r1, [r0] // Attempt Store-Exclusive
|
||||
CMP r2, #0 // Check if Store-Exclusive succeeded
|
||||
BNE _mutex_unlock // Store failed - retry immediately
|
||||
DMB // Required before releasing protected resource
|
||||
MOVS r0, #0 // Successfully unlocked.
|
||||
BX lr
|
||||
_mutex_unlock_fail:
|
||||
DMB
|
||||
MOV r0, #-1 // Already unlocked!
|
||||
BX lr
|
||||
|
7
sdcard.c
7
sdcard.c
|
@ -450,6 +450,13 @@ int sdcard_read(void *dev, void *_buf, uint32_t lba)
|
|||
return err;
|
||||
}
|
||||
|
||||
uint32_t sdcard_getsize(void *dev)
|
||||
{
|
||||
if (SD.card)
|
||||
return SD.card->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a Block from our Card
|
||||
*/
|
||||
|
|
1
sdcard.h
1
sdcard.h
|
@ -58,6 +58,7 @@ int sdcard_read(void *dev, void *_buf, uint32_t lba);
|
|||
int sdcard_write(void *dev, void *_buf, uint32_t lba);
|
||||
int sdcard_sense(void);
|
||||
int sdcard_detect(void);
|
||||
uint32_t sdcard_getsize(void *dev);
|
||||
void sdcard_hw_init(void);
|
||||
|
||||
|
||||
|
|
47
startup.c
47
startup.c
|
@ -22,6 +22,8 @@ static unsigned int sp;
|
|||
extern void main(void);
|
||||
extern void isr_exti(void);
|
||||
extern void isr_systick(void);
|
||||
extern void otg_fs_isr(void);
|
||||
extern void usb_fs_wkup_isr(void);
|
||||
|
||||
void isr_reset(void) {
|
||||
register unsigned int *src, *dst;
|
||||
|
@ -149,11 +151,54 @@ void (* const IV[])(void) =
|
|||
isr_empty, // USART3_IRQ 39
|
||||
isr_exti, // EXTI15_10_IRQ 40
|
||||
isr_empty, // RTC_ALARM_IRQ 41
|
||||
isr_empty, // USB_FS_WKUP_IRQ 42
|
||||
usb_fs_wkup_isr, // USB_FS_WKUP_IRQ 42
|
||||
isr_empty, // TIM8_BRK_TIM12_IRQ 43
|
||||
isr_empty, // TIM8_UP_TIM13_IRQ 44
|
||||
isr_empty, // TIM8_TRG_COM_TIM14_IRQ 45
|
||||
isr_empty, // TIM8_CC_IRQ 46
|
||||
isr_empty, // DMA1_STREAM7_IRQ 47
|
||||
isr_empty, // FSMC_IRQ
|
||||
isr_empty, // SDIO_IRQ
|
||||
isr_empty, // TIM5_IRQ
|
||||
isr_empty, // SPI3_IRQ
|
||||
isr_empty, // UART4_IRQ
|
||||
isr_empty, // UART5_IRQ
|
||||
isr_empty, // TIM6_DAC_IRQ
|
||||
isr_empty, // TIM7_IRQ
|
||||
isr_empty, // DMA2_STREAM0_IRQ
|
||||
isr_empty, // DMA2_STREAM1_IRQ
|
||||
isr_empty, // DMA2_STREAM2_IRQ
|
||||
isr_empty, // DMA2_STREAM3_IRQ
|
||||
isr_empty, // DMA2_STREAM4_IRQ
|
||||
isr_empty, // ETH_IRQ
|
||||
isr_empty, // ETH_WKUP_IRQ
|
||||
isr_empty, // CAN2_TX_IRQ
|
||||
isr_empty, // CAN2_RX0_IRQ
|
||||
isr_empty, // CAN2_RX1_IRQ
|
||||
isr_empty, // CAN2_SCE_IRQ
|
||||
otg_fs_isr, // OTG_FS_IRQ
|
||||
isr_empty, // DMA2_STREAM5_IRQ
|
||||
isr_empty, // DMA2_STREAM6_IRQ
|
||||
isr_empty, // DMA2_STREAM7_IRQ
|
||||
isr_empty, // USART6_IRQ
|
||||
isr_empty, // I2C3_EV_IRQ
|
||||
isr_empty, // I2C3_ER_IRQ
|
||||
isr_empty, // OTG_HS_EP1_OUT_IRQ
|
||||
isr_empty, // OTG_HS_EP1_IN_IRQ
|
||||
isr_empty, // OTG_HS_WKUP_IRQ
|
||||
isr_empty, // OTG_HS_IRQ
|
||||
isr_empty, // DCMI_IRQ
|
||||
isr_empty, // CRYP_IRQ
|
||||
isr_empty, // HASH_RNG_IRQ
|
||||
isr_empty, // FPU_IRQ
|
||||
isr_empty, // UART7_IRQ
|
||||
isr_empty, // UART8_IRQ
|
||||
isr_empty, // SPI4_IRQ
|
||||
isr_empty, // SPI5_IRQ
|
||||
isr_empty, // SPI6_IRQ
|
||||
isr_empty, // SAI1_IRQ
|
||||
isr_empty, // LCD_TFT_IRQ
|
||||
isr_empty, // LCD_TFT_ERR_IRQ
|
||||
isr_empty, // DMA2D_IRQ
|
||||
|
||||
};
|
||||
|
|
17
system.h
17
system.h
|
@ -5,7 +5,10 @@
|
|||
#define PLL_FULL_MASK (0x7F037FFF)
|
||||
extern uint32_t cpu_freq;
|
||||
void panic(void);
|
||||
void printbin(const uint8_t *buf, int len); /* Defined in uart.c */
|
||||
|
||||
extern int _mutex_lock(void *); /* defined in mutex.S */
|
||||
extern int _mutex_unlock(void *);
|
||||
|
||||
/* PIN CONFIG TARGET */
|
||||
#define BLUE_LED 4
|
||||
|
@ -427,4 +430,18 @@ static inline void nvic_irq_clear(uint8_t n)
|
|||
#define SDIO_MASK_CCRCFAILIE (1 << 0)
|
||||
|
||||
|
||||
|
||||
/* Reboot */
|
||||
|
||||
#define AIRCR *(volatile uint32_t *)(0xE000ED0C)
|
||||
#define AIRCR_VKEY (0x05FA << 16)
|
||||
# define AIRCR_SYSRESETREQ (1 << 2)
|
||||
|
||||
static inline void reboot(void)
|
||||
{
|
||||
AIRCR = AIRCR_SYSRESETREQ | AIRCR_VKEY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
14
uart.c
14
uart.c
|
@ -6,6 +6,7 @@
|
|||
* See LICENSE for details
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "uart.h"
|
||||
#include "system.h"
|
||||
|
||||
|
@ -116,3 +117,16 @@ int _write(void *r, uint8_t *text, int len)
|
|||
return len;
|
||||
}
|
||||
|
||||
/* commodity to print binary buffers */
|
||||
|
||||
void printbin(const uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i % 16) == 0)
|
||||
printf("\r\n%08x: ", i);
|
||||
printf("%02x ", buf[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
|
|
92
ui.c
92
ui.c
|
@ -13,6 +13,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "usecfs.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
/* Uncomment for device initialization */
|
||||
|
@ -42,6 +43,7 @@ static uint32_t offset = 0;
|
|||
#define MAX_PASSWORD 32
|
||||
|
||||
static int fsm_state = ST_LOCKED;
|
||||
static int sleeping = 0;
|
||||
|
||||
static char password[MAX_PASSWORD] = {};
|
||||
static int pin_idx = 0;
|
||||
|
@ -49,12 +51,36 @@ static int pin_idx = 0;
|
|||
|
||||
#define SLEEP_TIME (5000)
|
||||
|
||||
void ui_msg(const char *txt)
|
||||
static void ui_sleep(void)
|
||||
{
|
||||
display_scroll(NULL, 0);
|
||||
display_clear(NULL);
|
||||
display_text(6, txt);
|
||||
sleeping = 1;
|
||||
}
|
||||
|
||||
static int ui_wakeup(void)
|
||||
{
|
||||
last_action = jiffies;
|
||||
if (sleeping) {
|
||||
sleeping = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ui_vault_on(void)
|
||||
{
|
||||
ui_msg("Activating Vault");
|
||||
bridge_init();
|
||||
}
|
||||
|
||||
|
||||
void ui_msg(const char *txt)
|
||||
{
|
||||
ui_wakeup();
|
||||
display_scroll(NULL, 0);
|
||||
display_clear(NULL);
|
||||
display_text(6, txt);
|
||||
}
|
||||
|
||||
void lock(void)
|
||||
|
@ -64,7 +90,7 @@ void lock(void)
|
|||
fsm_state = ST_LOCKED;
|
||||
}
|
||||
|
||||
static void pwrst(void)
|
||||
static void pwdrst(void)
|
||||
{
|
||||
memset(password, 0, MAX_PASSWORD);
|
||||
pin_idx = 0;
|
||||
|
@ -74,8 +100,11 @@ int unlock(void)
|
|||
{
|
||||
uint8_t stored_uuid[UUID_LEN];
|
||||
if (pin_idx < 6) {
|
||||
display_text(6, "Failed.");
|
||||
pwrst();
|
||||
display_scroll(NULL, 0);
|
||||
display_clear(NULL);
|
||||
display_text(5, "Failed.");
|
||||
display_text(6, "Insert pin:");
|
||||
pwdrst();
|
||||
return -1;
|
||||
}
|
||||
display_scroll(NULL, 0);
|
||||
|
@ -84,7 +113,7 @@ int unlock(void)
|
|||
display_text(5, "Unlocking secret");
|
||||
if ((usecfs_init(password, 0, stored_uuid) == 0) &&
|
||||
(memcmp(stored_uuid, uuid, UUID_LEN) == 0)) {
|
||||
pwrst();
|
||||
pwdrst();
|
||||
fsm_state = ST_UNLOCKED;
|
||||
ui_msg("Device UNLOCKED");
|
||||
return 0;
|
||||
|
@ -96,8 +125,11 @@ int unlock(void)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
display_text(6, "Failed.");
|
||||
pwrst();
|
||||
display_scroll(NULL, 0);
|
||||
display_clear(NULL);
|
||||
display_text(5, "Failed.");
|
||||
display_text(6, "Insert pin:");
|
||||
pwdrst();
|
||||
fsm_state = ST_LOCKED;
|
||||
return -1;
|
||||
}
|
||||
|
@ -106,13 +138,21 @@ int unlock(void)
|
|||
|
||||
void ui_button_hold(uint16_t button)
|
||||
{
|
||||
last_action = jiffies;
|
||||
ui_wakeup();
|
||||
}
|
||||
|
||||
void ui_status(void)
|
||||
{
|
||||
display_scroll(NULL, 0);
|
||||
display_clear(NULL);
|
||||
display_text(5, "Status Report ");
|
||||
display_text(6, "Status OK ");
|
||||
}
|
||||
|
||||
void ui_sdcard_insert(void)
|
||||
{
|
||||
ui_wakeup();
|
||||
ui_msg("SD Card detected");
|
||||
last_action = jiffies;
|
||||
}
|
||||
|
||||
void ui_menu(char in)
|
||||
|
@ -125,27 +165,43 @@ void ui_menu(char in)
|
|||
display_text(7, "1. Status ");
|
||||
display_text(6, "0. Lockdown ");
|
||||
display_text(5, "Main Menu ");
|
||||
display_text(2, "4. Reboot ");
|
||||
display_text(2, "4. UART menu ");
|
||||
display_text(1, "3. SD format ");
|
||||
display_text(0, "2. USB vault ON ");
|
||||
switch (in) {
|
||||
case ' ':
|
||||
menu_scroll += 4;
|
||||
menu_scroll %= 0x40;
|
||||
display_scroll(NULL, menu_scroll);
|
||||
break;
|
||||
case '\r':
|
||||
menu_scroll -= 4;
|
||||
menu_scroll %= 0x40;
|
||||
display_scroll(NULL, menu_scroll);
|
||||
break;
|
||||
case '1':
|
||||
ui_status();
|
||||
break;
|
||||
case '2':
|
||||
ui_vault_on();
|
||||
break;
|
||||
case '0':
|
||||
reboot();
|
||||
panic();
|
||||
break;
|
||||
}
|
||||
menu_scroll %= 0x40;
|
||||
display_scroll(NULL, menu_scroll);
|
||||
}
|
||||
|
||||
void ui_button_press(uint16_t button)
|
||||
{
|
||||
int i;
|
||||
char c;
|
||||
if (ui_wakeup())
|
||||
c = 0;
|
||||
else
|
||||
c = bu2c(button);
|
||||
if (fsm_state == ST_LOCKED) {
|
||||
pwrst();
|
||||
pwdrst();
|
||||
ui_msg("Insert pin:");
|
||||
fsm_state = ST_PIN_ENTRY;
|
||||
return;
|
||||
|
@ -155,7 +211,6 @@ void ui_button_press(uint16_t button)
|
|||
for (i = 0; i < pin_idx; i++) {
|
||||
line[i] = '*';
|
||||
}
|
||||
c = bu2c(button);
|
||||
if ((c >= '0') && (c <='9')) {
|
||||
if (pin_idx < 16) {
|
||||
line[pin_idx] = 'X';
|
||||
|
@ -165,17 +220,13 @@ void ui_button_press(uint16_t button)
|
|||
if (c == '\r') {
|
||||
unlock();
|
||||
} else {
|
||||
display_scroll(NULL, 0);
|
||||
display_clear(NULL);
|
||||
display_text(7, line);
|
||||
display_text(6, "Insert pin:");
|
||||
}
|
||||
}
|
||||
if (fsm_state == ST_UNLOCKED)
|
||||
{
|
||||
ui_menu(bu2c(button));
|
||||
}
|
||||
last_action = jiffies;
|
||||
}
|
||||
|
||||
void ui_init(void)
|
||||
|
@ -208,8 +259,7 @@ void ui_init(void)
|
|||
void ui_keepalive(uint32_t timeslice)
|
||||
{
|
||||
if ((jiffies - last_action) > SLEEP_TIME) {
|
||||
display_scroll(NULL, 0);
|
||||
display_clear(NULL);
|
||||
ui_sleep();
|
||||
if (fsm_state == ST_PIN_ENTRY)
|
||||
lock();
|
||||
}
|
||||
|
|
368
usb.c
Normal file
368
usb.c
Normal file
|
@ -0,0 +1,368 @@
|
|||
#include <unicore-mx/stm32/gpio.h>
|
||||
#include <unicore-mx/stm32/rcc.h>
|
||||
#include <unicore-mx/stm32/f4/rcc.h>
|
||||
#include <unicore-mx/stm32/usart.h>
|
||||
#include <unicore-mx/cm3/nvic.h>
|
||||
#include <unicore-mx/usbd/usbd.h>
|
||||
#include <unicore-mx/usbd/class/msc.h>
|
||||
#include <unicore-mx/stm32/otg_fs.h>
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#include <wolfssl/wolfcrypt/aes.h>
|
||||
#include <wolfssl/wolfcrypt/chacha.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "system.h"
|
||||
#include "systick.h"
|
||||
#include "sdcard.h"
|
||||
|
||||
//#define USB_DEBUG
|
||||
#ifdef USB_DEBUG
|
||||
#define USB_DBG printf
|
||||
#define USB_DBG_BIN printbin
|
||||
#else
|
||||
#define USB_DBG(...) do{}while (0)
|
||||
#define USB_DBG_BIN(...) do{}while (0)
|
||||
#endif
|
||||
|
||||
#define CRYPTO_BLOCK_SIZE 64
|
||||
#define KEYSZ 32
|
||||
#define IVSZ 16
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
static const char VID[] = "0001";
|
||||
static const char PID[] = "0002";
|
||||
static const char PR[] = "0003";
|
||||
static const char iv_bytes[16] = {0x00, 0x00, 0x00, 0x00, 0xa8, 0xbb, 0x2a, 0x3e, 0x3c, 0xb7, 0x19, 0x27, 0x77, 0xbf, 0x3e, 0x60 };
|
||||
static struct usbd_device *usbd_dev = NULL;
|
||||
static uint8_t tmp_blk_rd[SECTOR_SIZE];
|
||||
static uint8_t tmp_blk_wr[SECTOR_SIZE];
|
||||
static uint32_t bridge_mutex = 1;
|
||||
|
||||
static int bridge_read_block(const usbd_msc_backend *backend, uint32_t lba, void *copy_to)
|
||||
{
|
||||
ChaCha cha;
|
||||
uint8_t crypto_tmp[CRYPTO_BLOCK_SIZE];
|
||||
uint32_t i;
|
||||
uint32_t sd_size = sdcard_getsize(NULL);
|
||||
volatile uint8_t *dst;
|
||||
uint8_t crypto_iv[16];
|
||||
if (lba > sd_size)
|
||||
return -1;
|
||||
if (lba < 2) {
|
||||
USB_DBG("SD: requested block %08x\r\n", lba);
|
||||
}
|
||||
/*
|
||||
if (lba == 0) {
|
||||
dst = copy_to;
|
||||
memcpy(copy_to, BootSector, SECTOR_SIZE);
|
||||
dst[SECTOR_SIZE - 2] = 0x55;
|
||||
dst[SECTOR_SIZE - 1] = 0xAA;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
memset(copy_to, 0, SECTOR_SIZE);
|
||||
dst = (uint8_t *)tmp_blk_rd;
|
||||
sdcard_read(NULL, dst, lba);
|
||||
wc_Chacha_SetKey(&cha, usecfs_getkey(), 32);
|
||||
memcpy(crypto_iv, iv_bytes, 16);
|
||||
*((uint32_t *)crypto_iv) = lba;
|
||||
wc_Chacha_SetIV(&cha, crypto_iv, 16);
|
||||
for (i = 0; i < SECTOR_SIZE / CRYPTO_BLOCK_SIZE; i++) {
|
||||
memcpy(crypto_tmp, dst + i * CRYPTO_BLOCK_SIZE, CRYPTO_BLOCK_SIZE);
|
||||
wc_Chacha_Process(&cha, dst + i * CRYPTO_BLOCK_SIZE, crypto_tmp, CRYPTO_BLOCK_SIZE);
|
||||
}
|
||||
if (lba < 2) {
|
||||
USB_DBG("Decrypted:\r\n");
|
||||
USB_DBG_BIN(dst, SECTOR_SIZE);
|
||||
}
|
||||
memcpy(copy_to, dst, SECTOR_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int bridge_write_block(const usbd_msc_backend *backend, uint32_t lba, const void *copy_from)
|
||||
{
|
||||
ChaCha cha;
|
||||
uint8_t crypto_tmp[CRYPTO_BLOCK_SIZE];
|
||||
uint32_t i;
|
||||
const uint8_t *src;
|
||||
uint8_t crypto_iv[16];
|
||||
uint32_t sd_size;
|
||||
|
||||
bridge_lock();
|
||||
sd_size = sdcard_getsize(NULL);
|
||||
if (lba > sd_size) {
|
||||
printf("SD error: attempting to write to block %u out of range\r\n", lba);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
if (lba == 0) {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
if (lba < 2) {
|
||||
USB_DBG("SD: provided block %u\r\n", lba);
|
||||
USB_DBG_BIN(copy_from, SECTOR_SIZE);
|
||||
}
|
||||
memcpy(tmp_blk_wr, copy_from, SECTOR_SIZE);
|
||||
src = (uint8_t *)tmp_blk_wr;
|
||||
wc_Chacha_SetKey(&cha, usecfs_getkey(), 32);
|
||||
memcpy(crypto_iv, iv_bytes, 16);
|
||||
*((uint32_t *)crypto_iv) = lba;
|
||||
wc_Chacha_SetIV(&cha, crypto_iv, 16);
|
||||
for (i = 0; i < SECTOR_SIZE / CRYPTO_BLOCK_SIZE; i++) {
|
||||
memcpy(crypto_tmp, src + i * CRYPTO_BLOCK_SIZE, CRYPTO_BLOCK_SIZE);
|
||||
wc_Chacha_Process(&cha, tmp_blk_wr + i * CRYPTO_BLOCK_SIZE, crypto_tmp, CRYPTO_BLOCK_SIZE);
|
||||
}
|
||||
sdcard_write(NULL, tmp_blk_wr, lba);
|
||||
bridge_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bridge_lock(void)
|
||||
{
|
||||
while(_mutex_lock(&bridge_mutex) == 0)
|
||||
;
|
||||
asm volatile ("cpsid i");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bridge_unlock(void)
|
||||
{
|
||||
asm volatile ("cpsie i");
|
||||
return _mutex_unlock(&bridge_mutex);
|
||||
}
|
||||
|
||||
struct usbd_msc_backend flash_backend = {
|
||||
.vendor_id = VID,
|
||||
.product_id = PID,
|
||||
.product_rev = PR,
|
||||
.block_count = 0,
|
||||
//.lock = bridge_lock,
|
||||
//.unlock = bridge_unlock,
|
||||
.read_block = bridge_read_block,
|
||||
.write_block = bridge_write_block,
|
||||
};
|
||||
|
||||
const usbd_backend *msc_target_usb_driver(void)
|
||||
{
|
||||
return USBD_STM32_OTG_FS;
|
||||
}
|
||||
|
||||
static const struct usb_string_descriptor string_lang_list = {
|
||||
.bLength = USB_DT_STRING_SIZE(1),
|
||||
.bDescriptorType = USB_DT_STRING,
|
||||
.wData = {
|
||||
USB_LANGID_ENGLISH_UNITED_STATES
|
||||
}
|
||||
};
|
||||
|
||||
const struct usb_string_descriptor usb_string_manuf = {
|
||||
.bLength = USB_DT_STRING_SIZE(10),
|
||||
.bDescriptorType = USB_DT_STRING,
|
||||
/* danielinux */
|
||||
.wData = {
|
||||
0x0064, 0x0061, 0x006e, 0x0069, 0x0065, 0x006c, 0x0069, 0x006e, 0x0075, 0x0078
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_string_descriptor usb_string_name = {
|
||||
.bLength = USB_DT_STRING_SIZE(42),
|
||||
.bDescriptorType = USB_DT_STRING,
|
||||
/* "Encrypted SD Card in Secure Storage device" */
|
||||
.wData = {
|
||||
0x0045, 0x006e, 0x0063, 0x0072, 0x0079, 0x0070, 0x0074, 0x0065, 0x0064, 0x0020, 0x0053, 0x0044,
|
||||
0x0020, 0x0043, 0x0061, 0x0072, 0x0064, 0x0020, 0x0069, 0x006e, 0x0020, 0x0053, 0x0065, 0x0063,
|
||||
0x0075, 0x0072, 0x0065, 0x0020, 0x0053, 0x0074, 0x006f, 0x0072, 0x0061, 0x0067, 0x0065, 0x0020,
|
||||
0x0064, 0x0065, 0x0076, 0x0069, 0x0063, 0x0065
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_string_descriptor usb_serialn = {
|
||||
.bLength = USB_DT_STRING_SIZE(3),
|
||||
.bDescriptorType = USB_DT_STRING,
|
||||
/* 000 */
|
||||
.wData = {
|
||||
0x0030, 0x0030, 0x0030
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_string_descriptor **string_data[1] = {
|
||||
(const struct usb_string_descriptor *[]) {
|
||||
&usb_string_manuf,
|
||||
&usb_string_name,
|
||||
&usb_serialn
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_device_descriptor msc_dev_desc= {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = 0x0110,
|
||||
.bDeviceClass = 0,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = 64,
|
||||
.idVendor = 0x1d50,
|
||||
.idProduct = 0xDAD0,
|
||||
.bcdDevice = 0x0200,
|
||||
.iManufacturer = 1,
|
||||
.iProduct = 2,
|
||||
.iSerialNumber = 3,
|
||||
.bNumConfigurations = 1
|
||||
};
|
||||
|
||||
static const struct __attribute__((packed)) {
|
||||
struct usb_config_descriptor config;
|
||||
struct usb_interface_descriptor msc_iface;
|
||||
struct usb_endpoint_descriptor msc_endp[2];
|
||||
} msc_config = {
|
||||
.config = {
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.wTotalLength = sizeof(msc_config),
|
||||
.bNumInterfaces = 1,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32
|
||||
},
|
||||
|
||||
.msc_iface = {
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_MSC,
|
||||
.bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI,
|
||||
.bInterfaceProtocol = USB_MSC_PROTOCOL_BBB,
|
||||
.iInterface = 0
|
||||
},
|
||||
|
||||
.msc_endp = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x01,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 0,
|
||||
}, {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x82,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 0,
|
||||
}}
|
||||
|
||||
};
|
||||
|
||||
static usbd_msc *ms;
|
||||
|
||||
static void msc_ep_set_config(usbd_device *usbd_dev,
|
||||
const struct usb_config_descriptor *cfg)
|
||||
{
|
||||
(void)cfg;
|
||||
|
||||
usbd_ep_prepare(usbd_dev, 0x01, USBD_EP_BULK, 64, USBD_INTERVAL_NA, USBD_EP_DOUBLE_BUFFER);
|
||||
usbd_ep_prepare(usbd_dev, 0x82, USBD_EP_BULK, 64, USBD_INTERVAL_NA, USBD_EP_DOUBLE_BUFFER);
|
||||
usbd_msc_start(ms);
|
||||
|
||||
}
|
||||
|
||||
static const struct usbd_info_string msc_string = {
|
||||
.lang_list = &string_lang_list,
|
||||
.count = 3,
|
||||
.data = string_data
|
||||
};
|
||||
|
||||
static const struct usbd_info msc_info = {
|
||||
.device = {
|
||||
.desc = &msc_dev_desc,
|
||||
.string = &msc_string
|
||||
},
|
||||
|
||||
.config = {{
|
||||
.desc = (const struct usb_config_descriptor *) &msc_config,
|
||||
.string = &msc_string
|
||||
}}
|
||||
|
||||
};
|
||||
|
||||
static void setup_callback(usbd_device *usbd_dev, uint8_t ep_addr,
|
||||
const struct usb_setup_data *setup_data)
|
||||
{
|
||||
(void) ep_addr; /* assuming ep_addr == 0 */
|
||||
|
||||
if (!usbd_msc_setup_ep0(ms, setup_data)) {
|
||||
usbd_ep0_setup(usbd_dev, setup_data);
|
||||
}
|
||||
}
|
||||
|
||||
static int usb_enabled = 0;
|
||||
|
||||
void usb_init(void)
|
||||
{
|
||||
if (usb_enabled == 0) {
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_OTGFS);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,
|
||||
GPIO9 | GPIO11 | GPIO12);
|
||||
gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12);
|
||||
nvic_enable_irq(NVIC_OTG_FS_IRQ);
|
||||
flash_backend.block_count = sdcard_getsize(NULL);
|
||||
usbd_dev = usbd_init(msc_target_usb_driver(), NULL, &msc_info);
|
||||
ms = usbd_msc_init(usbd_dev, 0x82, 64, 0x01, 64, &flash_backend);
|
||||
usbd_register_set_config_callback(usbd_dev, msc_ep_set_config);
|
||||
usbd_register_setup_callback(usbd_dev, setup_callback);
|
||||
usb_enabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_deinit(void)
|
||||
{
|
||||
if (usb_enabled) {
|
||||
rcc_periph_clock_disable(RCC_OTGFS);
|
||||
nvic_disable_irq(NVIC_OTG_FS_IRQ);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE,
|
||||
GPIO9 | GPIO11 | GPIO12);
|
||||
usb_enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t last_call = 0;
|
||||
void usb_poll(void)
|
||||
{
|
||||
bridge_lock();
|
||||
if (usb_enabled && usbd_dev) {
|
||||
if ((jiffies - last_call > 4)) {
|
||||
usbd_poll(usbd_dev, 0);
|
||||
last_call = jiffies;
|
||||
}
|
||||
}
|
||||
bridge_unlock();
|
||||
}
|
||||
|
||||
int bridge_init(void)
|
||||
{
|
||||
|
||||
int ret = 0;
|
||||
void *sdcard = sdcard_open();
|
||||
if (!sdcard)
|
||||
return -1;
|
||||
usb_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void otg_fs_isr(void)
|
||||
{
|
||||
last_call = jiffies;
|
||||
usbd_poll(usbd_dev, 0);
|
||||
}
|
||||
|
5
usb.h
Normal file
5
usb.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#ifndef USB_INCLUDED
|
||||
#define USB_INCLUDED
|
||||
void usb_init(void);
|
||||
void usb_poll(void);
|
||||
#endif
|
646
usecfs.c
Normal file
646
usecfs.c
Normal file
|
@ -0,0 +1,646 @@
|
|||
#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);
|
||||
}
|
20
usecfs.h
Normal file
20
usecfs.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef INC_USECFS
|
||||
#define INC_USECFS
|
||||
#define MAX_FILENAME 256
|
||||
#define MAX_OPEN_FILES 16
|
||||
#define UUID_LEN 64
|
||||
#include <stdint.h>
|
||||
|
||||
int usecfs_init(const char *password, int format, uint8_t *uuid);
|
||||
int usecfs_format(const uint8_t *uuid);
|
||||
int usecfs_mount(uint8_t *uuid);
|
||||
int usecfs_open(const char *name);
|
||||
int usecfs_creat(const char *name);
|
||||
int usecfs_read(int fd, void *data, uint32_t len);
|
||||
int usecfs_write(int fd, const void *data, uint32_t len);
|
||||
int usecfs_seek(int fd, int offset, int whence);
|
||||
int usecfs_truncate(int fd, uint32_t newsize);
|
||||
int usecfs_unlink(const char *filename);
|
||||
int usecfs_close(int fd);
|
||||
|
||||
#endif
|
13
usecfs_dev.h
Normal file
13
usecfs_dev.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef INC_USECFS_BLOCK
|
||||
#define INC_USECFS_BLOCK
|
||||
|
||||
#ifndef BLOCK_SIZE
|
||||
# define BLOCK_SIZE 4096
|
||||
#endif
|
||||
|
||||
void *block_open(void *args);
|
||||
int block_read(void *dev, void *_buf, uint32_t lba);
|
||||
int block_write(void *dev, const void *_buf, uint32_t lba);
|
||||
void block_close(void *dev);
|
||||
|
||||
#endif
|
|
@ -13,6 +13,9 @@
|
|||
#define HAVE_CHACHA
|
||||
#define HAVE_SHA256
|
||||
#define HAVE_PBKDF2
|
||||
#define HAVE_AES
|
||||
#define HAVE_AES_CBC
|
||||
#define HAVE_AES_DECRYPT
|
||||
|
||||
#define CUSTOM_RAND_GENERATE random_uint32
|
||||
#define CUSTOM_RAND_TYPE uint32_t
|
||||
|
@ -25,7 +28,6 @@
|
|||
#define SINGLE_THREADED
|
||||
|
||||
/* Disables - For minimum wolfCrypt build */
|
||||
#define NO_AES
|
||||
#define NO_CMAC
|
||||
#define NO_CODING
|
||||
#define NO_RSA
|
||||
|
|
Loading…
Reference in a new issue