From c958c4becb89cf4038aeccc896eb236d9ae7a9e8 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 4 Nov 2019 15:38:49 +0100 Subject: [PATCH] Added USB-MSC --- Makefile | 16 +- main.c | 10 +- mutex.S | 47 ++++ sdcard.c | 7 + sdcard.h | 1 + startup.c | 47 +++- system.h | 17 ++ uart.c | 14 ++ ui.c | 92 +++++-- usb.c | 368 +++++++++++++++++++++++++++ usb.h | 5 + usecfs.c | 646 ++++++++++++++++++++++++++++++++++++++++++++++++ usecfs.h | 20 ++ usecfs_dev.h | 13 + user_settings.h | 4 +- 15 files changed, 1273 insertions(+), 34 deletions(-) create mode 100644 mutex.S create mode 100644 usb.c create mode 100644 usb.h create mode 100644 usecfs.c create mode 100644 usecfs.h create mode 100644 usecfs_dev.h diff --git a/Makefile b/Makefile index 16df0b5..76e0b61 100644 --- a/Makefile +++ b/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 diff --git a/main.c b/main.c index 00b6deb..d546c46 100644 --- a/main.c +++ b/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) { diff --git a/mutex.S b/mutex.S new file mode 100644 index 0000000..822e9dd --- /dev/null +++ b/mutex.S @@ -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 + diff --git a/sdcard.c b/sdcard.c index 2a204b7..2b02680 100644 --- a/sdcard.c +++ b/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 */ diff --git a/sdcard.h b/sdcard.h index a25c4f7..0de1832 100644 --- a/sdcard.h +++ b/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); diff --git a/startup.c b/startup.c index ac126e4..fd97288 100644 --- a/startup.c +++ b/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 }; diff --git a/system.h b/system.h index a2fb417..b400031 100644 --- a/system.h +++ b/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 diff --git a/uart.c b/uart.c index 7d51215..3e61194 100644 --- a/uart.c +++ b/uart.c @@ -6,6 +6,7 @@ * See LICENSE for details */ #include +#include #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"); +} + diff --git a/ui.c b/ui.c index d47a6f4..d129d42 100644 --- a/ui.c +++ b/ui.c @@ -13,6 +13,7 @@ #include #include #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(); } diff --git a/usb.c b/usb.c new file mode 100644 index 0000000..ae81ee0 --- /dev/null +++ b/usb.c @@ -0,0 +1,368 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/usb.h b/usb.h new file mode 100644 index 0000000..3a42e75 --- /dev/null +++ b/usb.h @@ -0,0 +1,5 @@ +#ifndef USB_INCLUDED +#define USB_INCLUDED +void usb_init(void); +void usb_poll(void); +#endif diff --git a/usecfs.c b/usecfs.c new file mode 100644 index 0000000..ed2e8b9 --- /dev/null +++ b/usecfs.c @@ -0,0 +1,646 @@ +#include +#include +#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 +#include +#include +#ifdef CRYPTO +#define CRYPTO_BLOCK_SIZE 16 + +uint8_t crypto_tmp[CRYPTO_BLOCK_SIZE]; +uint8_t crypto_iv[CRYPTO_BLOCK_SIZE]; + +#include +#include + +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); +} diff --git a/usecfs.h b/usecfs.h new file mode 100644 index 0000000..6c4b1aa --- /dev/null +++ b/usecfs.h @@ -0,0 +1,20 @@ +#ifndef INC_USECFS +#define INC_USECFS +#define MAX_FILENAME 256 +#define MAX_OPEN_FILES 16 +#define UUID_LEN 64 +#include + +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 diff --git a/usecfs_dev.h b/usecfs_dev.h new file mode 100644 index 0000000..e2d08bb --- /dev/null +++ b/usecfs_dev.h @@ -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 diff --git a/user_settings.h b/user_settings.h index 6868df2..c61dbc7 100644 --- a/user_settings.h +++ b/user_settings.h @@ -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