Giter Club home page Giter Club logo

sboot_stm32's Introduction

LNX build WIN build OSX build

Secure USB DFU1.1 bootloader for STM32

Features

  • Small size. Fits in 4K ROM segment (ASM or no encryption, otherwise a bit more).
  • USB DFU1.1 compatible
  • Supported by dfu-util
  • Supported ciphers:
    • No encryption
    • ARCFOUR stream cipher
    • CHACHA20 stream cipher
    • RC5-32/12/16 block cipher (C and ASM implementation)
    • RC6-32/20/16 block cipher (C and ASM implementation)
    • GOST R 34.12-2015 "MAGMA" block cipher
    • RAIDEN block cipher
    • SPECK 64/128 block cipher
    • XTEA (classic and XTEA-1) block cipher
    • RTEA block cipher
    • BLOWFISH type block cipher
    • Rijndael AES-128/192/256 block cipher
  • Supported cipher modes for block ciphers:
    • Electronic Codebook (ECB)
    • Cipher Block Chaining (CBC)
    • Propagating CBC (PCBC)
    • Cipher Feedback (CFB)
    • Output Feedback (OFB)
    • Counter (CTR)
  • Supported firmware verification methods:
    • CRC (CRC32, CRC64)
    • Fowler-Noll-Vo (FNV-1A-32, FNV1A-64)
  • Separate interfaces for flash and EEPROM programming
  • Autoseal using RDP level 1 or 2 (prevents reading decrypted FW trough debug interface). Be careful when you set RDP to level 2. This operation is irreversible and disables all debug functions and option bytes programming.
  • Software for firmware encryption/decryption included
  • Supported STM32 families:
    • STM32L0x2
    • STM32L1xx
    • STM32L476xx (OTG FS in device mode)
    • STM32F103
    • STM32F105, STM32F107 (OTG FS in device mode)
    • STM32F0 series
    • STM32F3 series
    • STM32F4 series
    • STM32G4 series

Generic flow

Generic Flow

Usage:

Configuring bootloader

The bootloader can be configured through the make parameters. See CONFIG.md for details.

Building bootloader

  1. Prerequisites
  • GNU make
  • arm-none-eabi-gcc toolchaipren v4.9 or later to build bootloader
  • gcc toolchain to build fwcrypt software
  • CMSIS V4 or CMSIS V5.
  • Device peripheral access layer header files for STM32. See Vendor Template for details.
  • stm32.h STM32 universal header
  • optional st-util tool to program bootloader
  1. Makefile targets
  • make prerequisites to download required libs and headers
  • make mcu_target to build bootloader
  • make program to flash bootloader using st-flash
  • make crypter to build encryption software
  1. Makefile and environmental variables
Variable Default Value Description
CMSIS CMSIS path to CMSIS root folder
CMSISDEV $(CMSIS)/Device path to CMSIS device folder
OUTDIR build output folder for binaries
FWNAME firmware name for bootloader binary
SWNAME fwcrypt name for encrypter binary
  1. MCU targets
mcu_target MCU remarks
stm32l100x6a STM32L100C6-A
stm32l100x8a STM32L100R8-A
stm32l100xba STM32L100RB-A
stm32l100xc STM32L100RC tested
stm32l151x6a STM32L151C6-A, STM32L151R6-A
stm32l151x8a STM32L151C8-A, STM32L151R8-A, STM31L151V8-A
stm32l151xba STM32L151CB-A, STM32L151RB-A, STM31L151VB-A
stm32l151xc STM32L151CC, STM32L151QC, SRM32L151RC, STM32L151UC
stm32l151xd STM32L151QD, STM32L151RD, STM32L151VD, STM32L151ZD
stm32l151xe STM32L151QE, STM32L151RE, STM32L151VE, STM32L151ZE
stm32l152x6a STM32L152C6-A, STM32L152R6-A
stm32l152x8a STM32L152C8-A, STM32L152R8-A, STM31L152V8-A
stm32l152xba STM32L152CB-A, STM32L152RB-A, STM31L152VB-A
stm32l152xc STM32L152CC, STM32L152QC, SRM32L152RC, STM32L152UC
stm32l152xd STM32L152QD, STM32L152RD, STM32L152VD, STM32L152ZD
stm32l152xe STM32L152QE, STM32L152RE, STM32L152VE, STM32L152ZE
stm32l162xc STM32L162RC, STM32L162VC
stm32l162xd STM32L162QD, STM32L156RD, STM32L162VD, STM32L162ZD
stm32l162xe STM32L162QE, STM32L156RE, STM32L162VE, STM32L162ZE
stm32l052x6 STM32L052K6, STM32L052T6, STM32L052C6, STM32L052R6
stm32l052x8 STM32L052K8, STM32L052T8, STM32L052C8, STM32L052R8 tested, default
stm32l053x6 STM32L053C6, STM32L053R6
stm32l053x8 STM32L053C8, STM32L053R8
stm32l062x8 STM32L062K8
stm32l063x8 STM32L063C8, STM32L063R8
stm32l072v8 STM32L072V8
stm32l072xb STM32L072KB, STM32L072CB, STM32L072RB, STM32L072VB tested
stm32l072xz STM32L072KZ, STM32L072CZ, STM32L072RZ, STM32L072VZ
stm32l073v8 STM32L073V8
stm32l073xb STM32L073CB, STM32L073RB, STM32L073VB
stm32l073xz STM32L073CZ, STM32L073RZ, STM32L073VZ
stm32l476xc STM32L476RC, STM32L476VC
stm32l476xe STM32L476RE, STM32L476JE, STM32L476ME, STM32L476VE
stm32l476xg STM32L476RG, STM32L476JG, STM32L476MG, STM32L476VG tested
stm32f103x6 STM32F103T6, STM32F103C6, STM32F103R6
stm32f103x8 STM32F103T8, STM32F103C8, STM32F103R8, STM32f103V8 tested
stm32f105xb STM32F105RB, STM32F105VB tested
stm32f107xb STM32F107RB, STM32F107VB tested
stm32l433xb STM32L433CB, STM32L433RB
stm32l433xc STM32L433CC, STM32L433RC, STM32L433VC tested
stm32f070x6 STM32F070C6
stm32f070xb STM32F070CB tested
stm32f429xe STM32F429xE series (single bank mode)
stm32f429xg STM32F429xG series (single bank mode)
stm32f429xi STM32F429xI series (single and dual bank) tested
stm32g431x6 STM32G431x6, STM32G441x6
stm32g431x8 STM32G431x8, STM32G441x8
stm32g431xb STM32G431xB, STM32G441xB tested G431RB
stm32g474xb STM32G471xB, STM32G473xB, STM32G474xB, STM32G483xB
stm32g474xc STM32G471xC, STM32G473xC, STM32G474xC, STM32G483xC
stm32g474xe STM32G471xE, STM32G473xE, STM32G474xE, STM32G483xE tested G747RE
stm32f303xe STM32F303xE tested
stm32f373xc STM32F373xC tested

Adjusting user firmware

  • Check bootloader's linker map for the __app_start address. This is the new ROM origin for the user firmware (ISR vectors).
  • Adjust your linker script to set new ROM origin and ROM length.

Utilizing usbd core and usbd driver from bootloader in the user firmware

  • Check bootloader's linker map for the usbd_poll entry point and usbd driver (usbd_devfs, usbd_otgfs, e.t.c. depends used MCU). It's located just after the .isr_vector section.
  • Add address for usbd_driver structure to your linker script. For example usbd_drv = 0x08000040;
  • Add address for usbd_poll entry point to your linker script. For example usbd_poll = 0x08000074;
  • Add extern struct usbd_driver usbd_drv; driver declaration to your code.
  • Include at least "usbd_core.h" and "usb_std.h" to your code.

Now you can use the usbd core and driver from the bootloader in your application. Don't forget to set GPIO and RCC for USB according to MCU requirements.

Activating bootloader

  • Write DFU_BOOTKEY at DFU_BOOTKEY_ADDR (RAM top by default) and make a software reset.
  • Assert DFU_BOOTSTRAP_PIN on DFU_BOOTSTRAP_PORT on startup (optional).
  • Make a double reset during the DFU_DBLRESET_MS period (optional).

Encrypting user firmware

We provide a utility for encryption and decryption of firmware images. At this moment, only raw binary files are supported.

To encrypt:

fwcrypt -e -i infile.bin -o outfile.bin

To decrypt:

fwcrypt -d -i infile.bin -o outfile.bin

sboot_stm32's People

Contributors

aftomahawk avatar alexispolti avatar dmitrystu avatar dzarda avatar fabianinostroza avatar rbm78bln avatar shawnchain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sboot_stm32's Issues

Checksum documentation

It's not entirely obvious how the firmware checksum validation works. I seem to have some idea but would like confirmation.

  • Encrypter appends checksum and verifies that remainder reaches zero only at the end of image
  • Bootloader verifies the whole flash region (_APP_START up until __romend)

Does this mean that the application image should be linked with the resultant size of __romend - _APP_START - 4 in order to guarantee correct checksum verification?

DATA_EEPROM_END undefined error

I am building for the STM32L072KZ. When attempting to build using the provided config.h with cipher disabled. I get DATA_EEPROM_END undefined as an error. Are there any other definitions I need to add to the config.h

Clear FLASH_SR in stm32f0xx.S

I might be wrong but I have some doubts about the way to clear the FLASH_SR in mcu/stm32f00x.S.
Current code is (line 397)

/* clear FLASH_SR */
    movs    r4, 0x64
    str     r4, [r3, FLASH_SR]

But looking at stm32f072v8 and stm32f0x1stm32f0x2stm32f0x8 reference manuals, the correct value to write should be 0x34 (or 0x14) if I'm not mistaken. Did I miss something?

Firmware stuck at start when using MX_USB_DEVICE_Init(); in user firmware.

I built the bootloader for F070CB. I can upload my demo firmware and it works just fine. The issue appeared when I decided to make a demo firmware that jumps to bootloader from firmware with a command received from PC over virtual COM port.
If I include MX_USB_DEVICE_Init(); in int main(void) my LED turns on at start and stops there.
Is the issue caused by using different USB drivers from bootloader? Also reset after USB detach seem buggy. It doesn't matter if it is enabled or disabled, I get a reset when I unplug and plug USB cable back in.

EDIT:
I am configuring USB interface as CDC Virtual Port Com in STM32CubeIDE.

missing headers?

during compile I get this error:

src/descriptors.c:19:19: fatal error: stm32.h: No such file or directory
#include "stm32.h"

I think I'm missing a required dependency.

Unable programm if rdp>0

If DFU_SEAL_LEVEL != 0 i recive state(10) = dfuERROR, status(4) = Memory erase function failed.
What i do wrong ?
cpu stm32f103c8

dfu-util -v -d 0483:df11 -D outfile.bin 0x8002000
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 0483:df11
Run-time device DFU version 0110
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 0110
Device returned transfer size 128
Copying data from PC to DFU device
Download [ ] 0% 0 bytes failed!
state(10) = dfuERROR, status(4) = Memory erase function failed

config


/* DEFAULT CONFIG STARTS HERE */
/* Skip unwanted dfuDNLOAD_SYNC phase. Slightly improve speed, but don't meets DFU1.1 state diagram */
#ifndef DFU_DNLOAD_NOSYNC
#define DFU_DNLOAD_NOSYNC   _ENABLE
#endif
/** Add extra DFU interface for EEPROM */
#ifndef DFU_INTF_EEPROM
#define DFU_INTF_EEPROM     _DISABLE
#endif
/** Firmware can be uploaded from device */
#ifndef DFU_CAN_UPLOAD
#define DFU_CAN_UPLOAD     _DISABLE
#endif
/** Handle DFU_DETACH request in DFU mode. System reset will be issued. */
#ifndef DFU_DETACH
#define DFU_DETACH          _ENABLE
#endif
/** Whether application image is verified by a checksum algorithm */
#ifndef DFU_VERIFY_CHECKSUM
#define DFU_VERIFY_CHECKSUM CRC64FAST
#endif
/** Memory Readout Protection level **/
#ifndef DFU_SEAL_LEVEL
#define DFU_SEAL_LEVEL    1
#endif
/* USB VID */
#ifndef DFU_VENDOR_ID
#define DFU_VENDOR_ID       0x0483
#endif
/* USB PID */
#ifndef DFU_DEVICE_ID
#define DFU_DEVICE_ID       0xDF11
#endif
/* USB manufacturer string */
#ifndef DFU_STR_MANUF
#define DFU_STR_MANUF       "Cdi.biz.ua"
#endif
/* USB product sting */
#ifndef DFU_STR_PRODUCT
#define DFU_STR_PRODUCT     "Bootloader"
#endif
/* USB string for DFU configureation string descriptor. */
#ifndef DFU_DSC_CONFIG
#define DFU_DSC_CONFIG      _ENABLE
#endif
#ifndef DFU_STR_CONFIG
#define DFU_STR_CONFIG      "DFU"
#endif
/* USB string for DFU flash interface string descriptor. */
#ifndef DFU_DSC_FLASH
#define DFU_DSC_FLASH       _ENABLE
#endif
#ifndef DFU_STR_FLASH
#define DFU_STR_FLASH       "Internal flash"
#endif
/* USB string for DFU EEPROM interface sreing descriptor */
#ifndef DFU_DSC_EEPROM
#define DFU_DSC_EEPROM     _DISABLE
#endif
#ifndef DFU_STR_EEPROM
#define DFU_STR_EEPROM       "Internal EEPROM"
#endif
/* USB EP0 size. Must be 8 for USB FS */
#define DFU_EP0_SIZE        8
/* DFU properties */
#ifndef DFU_POLL_TIMEOUT
#define DFU_POLL_TIMEOUT    20
#endif
#ifndef DFU_DETACH_TIMEOUT
#define DFU_DETACH_TIMEOUT  200
#endif
#ifndef DFU_BLOCKSZ
#define DFU_BLOCKSZ         0x80
#endif
/* 32 bit DFU bootkey value */
#ifndef DFU_BOOTKEY
#define DFU_BOOTKEY         0x77777777
#endif
/* DFU bootkey address. Top of the ram by default. _AUTO, _DISABLE or set address.
 * May be enabled internally. */
#ifndef DFU_BOOTKEY_ADDR
#define DFU_BOOTKEY_ADDR    0x20001000
#endif
/* DFU bootstrap port/pin settings. Set GPIOx or _DISABLE */
#ifndef DFU_BOOTSTRAP_GPIO
#define DFU_BOOTSTRAP_GPIO  _DISABLE
#endif
#ifndef DFU_BOOTSTRAP_PIN
#define DFU_BOOTSTRAP_PIN   2
#endif
/* Active bootstrap pin logic level. _HIGH, _LOW */
#ifndef DFU_BOOTSTRAP_LEVEL
#define DFU_BOOTSTRAP_LEVEL  _LOW
#endif
/* Pullup or pulldown settings for the bootstrap pin _AUTO, _DISABLE, _HIGH, _LOW */
#ifndef DFU_BOOTSTRAP_PULL
#define DFU_BOOTSTRAP_PULL  _DISABLE
#endif
/* Double reset waiting time in mS. _DISABLE or time in mS */
#ifndef DFU_DBLRESET_MS
#define DFU_DBLRESET_MS    500
#endif
/* User application address. _AUTO or page aligned address.
 * for _AUTO check __app_start address in output linker map file*/
#ifndef DFU_APP_START
#define DFU_APP_START       0x8002000 
#endif
/* User application size. _AUTO or required size in bytes. */
#ifndef DFU_APP_SIZE
#define DFU_APP_SIZE        _AUTO
#endif

i change DFU_STR_FLASH
Found DFU: [0483:df11] ver=0100, devnum=59, cfg=1, intf=0, path="1-1", alt=0, name="@internal Flash /0x08002000/56*1Kg", serial="9488CE25"
and still have error

Device returned transfer size 128
DfuSe interface name: "Internal Flash   "
Downloading to address = 0x08002000, size = 37008
Download        [                         ]   0%            0 bytesstate(10) = dfuERROR, status(4) = Memory erase function failed
Wrong state after command "ERASE_PAGE" download

Need a checksum only feature in fwcrypt

If one flashes an sboot_stm32 bootblock, which can only be performed with a programmer connected to the SWD interfaces, and then continued to flash the 'application' through the same SWD interfaces, then the device will not boot because there is no trailing checksum in the 'application' when flashed raw like that.

One could switch, then dfu-flash the application signed and encrypted of course, the workaround. But for expediency it would have been 'nice' if fwcrypt could also make a checksummed, but not encrypted, image that could be flashed via SWD.

Suggest adding a -C (uppercase) to suppress enCryption ala the following so that the tool can be leveraged to construct the configured checksum'd raw binary image:

diff --git a/src/encrypter.c b/src/encrypter.c
index 9d67e98..561bba4 100644
--- a/src/encrypter.c
+++ b/src/encrypter.c
@@ -39,6 +39,7 @@ static void exithelp(void) {
            "\t -d Decrypt\n"
            "\t -n No output (dry run)\n"
            "\t -c Without checksum signature\n"
+           "\t -C Without encryption/decryption\n"
            "\t -v VID:PID append DFU suffix (encrypt only)\n"
     );
     exit(0);
@@ -128,6 +129,7 @@ int main(int argc, char **argv)
 {
     int dir = 1;
     int crc = 1;
+    int crypt = 1;
     int dry = 0;
     char *infile = NULL;
     char *outfile = NULL;
@@ -136,7 +138,7 @@ int main(int argc, char **argv)
 
     opterr = 0;
 
-    while ((c = getopt(argc, argv, "edchni:o:v:")) != -1)
+    while ((c = getopt(argc, argv, "edcChni:o:v:")) != -1)
         switch (c)
         {
         case 'e':
@@ -148,6 +150,9 @@ int main(int argc, char **argv)
         case 'c':
             crc = 0;
             break;
+	case 'C':
+	    crypt = 0;
+	    break;
         case 'n':
             dry = 1;
             break;
@@ -228,11 +233,13 @@ int main(int argc, char **argv)
 #endif
 
 #if(DFU_CIPHER != _DISABLE)
-        if (length % aes_blksize) {
-            length += (aes_blksize - (length % aes_blksize));
+	if (crypt) {
+            if (length % aes_blksize) {
+                length += (aes_blksize - (length % aes_blksize));
+            }
+            printf("Encrypting %zd bytes using %s cipher.\n", length, aes_name);
+            aes_encrypt(buf, buf, length);
         }
-        printf("Encrypting %zd bytes using %s cipher.\n", length, aes_name);
-        aes_encrypt(buf, buf, length);
 #endif
 
         if (vidpid != 0) {
@@ -253,8 +260,10 @@ int main(int argc, char **argv)
     } else {
 
 #if(DFU_CIPHER != _DISABLE)
-        printf("Decrypting %zd bytes using %s cipher.\n", length, aes_name);
-        aes_decrypt(buf, buf, length);
+	if (crypt) {
+            printf("Decrypting %zd bytes using %s cipher.\n", length, aes_name);
+            aes_decrypt(buf, buf, length);
+	}
 #endif
 
 #if (DFU_VERIFY_CHECKSUM != _DISABLE)

Compilation with -Werror

I added -Werror, and had DFU_CAN_UPLOAD = _DISABLE:

src/bootloader.c:109:21: error: 'dfu_upload' defined but not used [-Werror=unused-function]
109 | static usbd_respond dfu_upload(usbd_device *dev, size_t blksize) {
| ^~~~~~~~~~

All this requires is a '#if (DFU_CAN_UPLOAD == _ENABLE) / #endif' around dfu_upload function.

Are you willing to investigate, and support -Werror?

Build fails with linker errors

make bootloader FWCPU='-mcpu=cortex-m3' \
                   FWSTARTUP='mcu/stm32f105.S' \
                   FWDEFS='STM32F1 STM32F107xC HSE_25MHZ USBD_VBUS_DETECT' \
                   LDPARAMS='ROMLEN=128K RAMLEN=20K'
make[1]: Entering directory '/home/polsaker/build/sboot_stm32'
compiling src/arc4.c
compiling src/chacha.c
compiling src/gost.c
compiling src/raiden.c
compiling src/rc5.c
compiling src/speck.c
compiling src/xtea.c
compiling src/xtea1.c
compiling src/blowfish.c
compiling src/rtea.c
compiling src/rc6.c
compiling src/rijndael.c
compiling src/magma.c
compiling src/checksum.c
compiling src/crypto.c
assembling mcu/stm32f105.S
compiling src/descriptors.c
In file included from usb/inc/usb.h:22,
                 from src/descriptors.c:21:
usb/inc/usbd_core.h:38:1: warning: "/*" within comment [-Wcomment]
   38 | /** @} */
      |  
compiling src/bootloader.c
In file included from usb/inc/usb.h:22,
                 from src/bootloader.c:21:
usb/inc/usbd_core.h:38:1: warning: "/*" within comment [-Wcomment]
   38 | /** @} */
      |  
assembling src/rc5a.S
assembling src/chacha_a.S
assembling src/rc6a.S
building module usb
make[2]: Entering directory '/home/polsaker/build/sboot_stm32/usb'
make /home/polsaker/build/sboot_stm32/build/objfw/libusb.a
make[3]: Entering directory '/home/polsaker/build/sboot_stm32/usb'
compiling src/usbd_core.c
compiling src/usbd_stm32f103_devfs.c
compiling src/usbd_stm32f105_otgfs.c
src/usbd_stm32f105_otgfs.c: In function 'ep_read':
src/usbd_stm32f105_otgfs.c:335:13: warning: 'packed' attribute ignored for type 'uint32_t *' {aka 'long unsigned int *'} [-Wattributes]
  335 |             *(__attribute__((packed))uint32_t*)buf = _t;
      |             ^
src/usbd_stm32f105_otgfs.c: In function 'ep_write':
src/usbd_stm32f105_otgfs.c:364:9: warning: 'packed' attribute ignored for type 'uint32_t *' {aka 'long unsigned int *'} [-Wattributes]
  364 |         *_fifo = *(__attribute__((packed)) uint32_t*)buf;
      |         ^
compiling src/usbd_stm32f429_otgfs.c
compiling src/usbd_stm32f429_otghs.c
compiling src/usbd_stm32f446_otgfs.c
compiling src/usbd_stm32l052_devfs.c
compiling src/usbd_stm32l100_devfs.c
compiling src/usbd_stm32l433_devfs.c
compiling src/usbd_stm32l476_otgfs.c
assembling src/usbd_stm32f103_devfs_asm.S
assembling src/usbd_stm32l052_devfs_asm.S
assembling src/usbd_stm32l100_devfs_asm.S
a - obj/usbd_core.o
a - obj/usbd_stm32f103_devfs.o
a - obj/usbd_stm32f105_otgfs.o
a - obj/usbd_stm32f429_otgfs.o
a - obj/usbd_stm32f429_otghs.o
a - obj/usbd_stm32f446_otgfs.o
a - obj/usbd_stm32l052_devfs.o
a - obj/usbd_stm32l100_devfs.o
a - obj/usbd_stm32l433_devfs.o
a - obj/usbd_stm32l476_otgfs.o
a - obj/usbd_stm32f103_devfs_asm.o
a - obj/usbd_stm32l052_devfs_asm.o
a - obj/usbd_stm32l100_devfs_asm.o
make[3]: Leaving directory '/home/polsaker/build/sboot_stm32/usb'
make[2]: Leaving directory '/home/polsaker/build/sboot_stm32/usb'
make -f ldscript.mk ROMLEN=128K RAMLEN=20K OUTFILE=build/objfw/script.ld
make[2]: Entering directory '/home/polsaker/build/sboot_stm32'
Building linker script
make[2]: Leaving directory '/home/polsaker/build/sboot_stm32'
building bootloader
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: build/objfw/bootloader.o (symbol from plugin): in function `main':
(.text+0x0): multiple definition of `aes_blksize'; build/objfw/crypto.o (symbol from plugin):(.text+0x0): first defined here
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: build/objfw/bootloader.o (symbol from plugin): in function `main':
(.text+0x0): multiple definition of `aes_name'; build/objfw/crypto.o (symbol from plugin):(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:120: build/firmware.elf] Error 1
make[1]: Leaving directory '/home/polsaker/build/sboot_stm32'
make: *** [Makefile:469: stm32f107xb] Error 2

happened in the stm32f107xb target

Platform init

Ideally the boot loader should provide a platform_init() type function (by default it does nothing and is weak) which is executed before any of the boot loader verification functions are run, ideally it should be called as early as possible.

The idea behind this is that it would allow the system clock to be configured to the fastest available for the platform, this would have a dramatic effect things like PKI signature verification.

Boot pin inversion

Boot pin is configured for LOW to enter bootloader, I propose a change to allow the logic to be inverted from the config file.

stm32l4xx.S (as an example)

.L_scan_bootstrap:
    ldr     r2, [r1, #GPIO_IDR] 
 #if (DFU_BOOTSTRAP_GPIO_ACTIVE_LEVEL == _HIGH)
    eor     r2, #(1<<(DFU_BOOTSTRAP_PIN))
#endif
    lsrs    r2, #(DFU_BOOTSTRAP_PIN + 1)    //Pin -> CF

and in config.h

#define _HIGH 1
#define _LOW 0

#define DFU_BOOTSTRAP_GPIO_ACTIVE_LEVEL   _HIGH

Timeout for inactivity.

To prevent DOSing of the Firmware by remaining locked up in the bootloader. Should something unexpected (?) result in the bootloader being activated, allow us to add an optional configurable activity-reset-able timeout for the usbd_poll loop. An option to block timeout when a firmware download is partial perhaps?

Support multiple DFU transports? USART?

Consider allow adding another polling object in the loop so that multiple transports can be supported simultaneously. For instance, as per https://www.st.com/resource/en/application_note/cd00264342-usart-protocol-used-in-the-stm32-bootloader-stmicroelectronics.pdf, one could conceivably simultaneously support DFU on the USB bus, or serial flashing via a selected serial port. I can imagine this opening the door to USART, LIN, CAN, I2C, ETH & SDCard as transports to approach the functionality of the ST built-in bootloader feature set.

STM32L475RC

Tested and working on the STM32L475RC as it's what I've been using to add my changes to the bootloader.

Compiling bootloader for stm32f103x8

Hello,
I have installed the prerequisites as mentioned in order to compile bootloader. I have also correctly edited the MakeFile under the root directory as well in the ./usb directory here.

Attached below is compressed folder of the cloned repo after some adjustment in the file structure.
sboot_stm32.zip

The directory structure looks like the following:

-<sboot_stm32>                   // as cloned locally
-<CMSIS_5>                       // as downloaded
      |
      +--  <CMSIS>
      +--  <Device>
      +--   .
      +--   .
      +--   .
      +--   <README.md>

After I ran make stm32f103x8, the output from the terminal is as follows:

D:\Documents\Projects\sboot_stm32>make stm32f103x8
Could Not Find D:\Documents\Projects\sboot_stm32\build\firmware*
Could Not Find D:\Documents\Projects\sboot_stm32\build\objfw\script.ld
make bootloader FWCPU='-mcpu=cortex-m3' \
                           FWSTARTUP='mcu/stm32f103.S' \
                           FWDEFS='STM32F1 STM32F103x6 USBD_ASM_DRIVER' \
                           LDPARAMS='ROMLEN=64K RAMLEN=20K'
make[1]: Entering directory `D:/Documents/Projects/sboot_stm32'
compiling src/arc4.c
compiling src/chacha.c
compiling src/gost.c
compiling src/raiden.c
compiling src/rc5.c
compiling src/speck.c
compiling src/xtea.c
compiling src/xtea1.c
compiling src/blowfish.c
compiling src/rtea.c
compiling src/rc6.c
compiling src/rijndael.c
compiling src/magma.c
compiling src/checksum.c
compiling src/crypto.c
assembling mcu/stm32f103.S
compiling src/descriptors.c
compiling src/bootloader.c
assembling src/rc5a.S
assembling src/chacha_a.S
assembling src/rc6a.S
building module usb
make[2]: Entering directory `D:/Documents/Projects/sboot_stm32/usb'
Could Not Find D:\Documents\Projects\sboot_stm32\usb\cdc_loop.*
make D:/Documents/Projects/sboot_stm32/build/objfw/libusb.a
make[3]: Entering directory `D:/Documents/Projects/sboot_stm32/usb'
compiling src/usbd_core.c
compiling src/usbd_stm32f103_devfs.c
src/usbd_stm32f103_devfs.c:64:13: note: #pragma message: PMA memory size is not defined. Use 512 bytes by default
     #pragma message "PMA memory size is not defined. Use 512 bytes by default"
             ^
compiling src/usbd_stm32f105_otgfs.c
compiling src/usbd_stm32f429_otgfs.c
compiling src/usbd_stm32f429_otghs.c
compiling src/usbd_stm32f446_otgfs.c
compiling src/usbd_stm32f446_otghs.c
compiling src/usbd_stm32l052_devfs.c
compiling src/usbd_stm32l100_devfs.c
compiling src/usbd_stm32l433_devfs.c
compiling src/usbd_stm32l476_otgfs.c
assembling src/usbd_stm32f103_devfs_asm.S
assembling src/usbd_stm32l052_devfs_asm.S
assembling src/usbd_stm32l100_devfs_asm.S
a - obj/usbd_core.o
a - obj/usbd_stm32f103_devfs.o
a - obj/usbd_stm32f105_otgfs.o
a - obj/usbd_stm32f429_otgfs.o
a - obj/usbd_stm32f429_otghs.o
a - obj/usbd_stm32f446_otgfs.o
a - obj/usbd_stm32f446_otghs.o
a - obj/usbd_stm32l052_devfs.o
a - obj/usbd_stm32l100_devfs.o
a - obj/usbd_stm32l433_devfs.o
a - obj/usbd_stm32l476_otgfs.o
a - obj/usbd_stm32f103_devfs_asm.o
a - obj/usbd_stm32l052_devfs_asm.o
a - obj/usbd_stm32l100_devfs_asm.o
make[3]: Leaving directory `D:/Documents/Projects/sboot_stm32/usb'
make[2]: Leaving directory `D:/Documents/Projects/sboot_stm32/usb'
make -f ldscript.mk ROMLEN=64K RAMLEN=20K OUTFILE=build/objfw/script.ld
make[2]: Entering directory `D:/Documents/Projects/sboot_stm32'
Building linker script
make[2]: Leaving directory `D:/Documents/Projects/sboot_stm32'
building bootloader
c:/program files (x86)/gnu tools arm embedded/4.9 2015q3/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/bin/ld.exe: cannot open linker script file build/objfw/script.ld: No such file or directory
collect2.exe: error: ld returned 1 exit status
make[1]: *** [build/firmware.elf] Error 1
make[1]: Leaving directory `D:/Documents/Projects/sboot_stm32'
make: *** [stm32f103x8] Error 2

The linker file is not generated at the location as shown here

I would humbly request you and anyone who can shine some light on this to kindly help me out. in solving the error as shon above
Thanks in advance for your time

Multiple Memory Overflow Vulnerabilities In dfu_control

The definition of the dfu_control function is as follows:


static usbd_respond dfu_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) {

req is receive from the external usb device.

it's struct is as follows:

/**\brief Represents generic USB control request.*/
typedef struct {
    uint8_t     bmRequestType;  /**<\brief This bitmapped field identifies the characteristics of
                                 * the specific request.*/
    uint8_t     bRequest;       /**<\brief This field specifies the particular request.*/
    uint16_t    wValue;         /**<\brief It is used to pass a parameter to the device, specific to
                                 * the request.*/
    uint16_t    wIndex;         /**<\brief It is used to pass a parameter to the device, specific to
                                 * the request.*/
    uint16_t    wLength;        /**<\brief This field specifies the length of the data transferred
                                 * during the second phase of the control transfer.*/
    uint8_t     data[];         /**<\brief Data payload.*/
} usbd_ctlreq;

BUG:

        case USB_DFU_DNLOAD:
            return dfu_dnload(req->data, req->wLength);
        case USB_DFU_UPLOAD:
            return dfu_upload(dev, req->wLength);

for USB_DFU_DNLOAD case, if req->wLength > the sizeof req->data , it could trigger buffer overflow in dfu_dnload.

for USB_DFU_UPLOAD case, if req->wLength > the sizeof dev->status.data_ptr , it could trigger buffer overflow in dfu_upload.

static usbd_respond dfu_upload(usbd_device *dev, size_t blksize) {
    switch (dfu_data.bState) {
    case USB_DFU_STATE_DFU_IDLE:
    case USB_DFU_STATE_DFU_UPLOADIDLE:
        if (dfu_data.remained == 0) {
            dev->status.data_count = 0;
            return dfu_set_idle();
        } else if (dfu_data.remained < DFU_BLOCKSZ) {
            blksize = dfu_data.remained;
        }
        aes_encrypt(dev->status.data_ptr, dfu_data.dptr, blksize);  // overflow !!!

stm32g491 support?

My WAG and heads up, stuff like (untested, I am a few weeks away from this being a priority) is missing:

    stm32g491xe \:
            ${MAKE} bootloader FWCPU='-mcpu=cortex-m4' \
                    FWSTARTUP='mcu/stm32g4xx.S' \
                    FWDEFS='STM32G4 STM32G491xx' \
                    LDPARAMS='ROMLEN=512K RAMLEN=112K USBD_ASM_DRIVER'

But I am sure that is flawed since usb driver, albeit similar to stm32f4 from the HAL perspective, might not be from the lower level driver perspective. IDK. I have a NUCLEO-G491RE in my hands where I am working on porting an application from stm32f429 and noticed that to use sboot_stm32, it was borken. Once application port and bringup is done, then I can test sboot_stm32.

SWD Enabled.

When encryption is enabled and we’re in ROP1 it would probably be a good idea to reconfigure SWD pins to disable them while uploading firmware.

Theres a potential vector here in that I believe that even with ROP1 enabled RAM can be read and written to. It cannot be completely mitigated against because I believe that a “bad actor” could inject breakpoints and step over the code which disables SWD, but I think it’s worth considering. There may be other ways of mitigating security issues.

cannot open linker script file build/objfw/script.

Hi, firstly, thank you for creating this, it's just what I've been looking for.
I'm having trouble compiling it. I am running on macOS Catalina v10.15.2.

I'm having trouble building the linker.

/Applications/Xcode.app/Contents/Developer/usr/bin/make -f ldscript.mk ROMLEN=64K RAMLEN=20K OUTFILE=build/objfw/script.ld
Building linker script
building bootloader
/usr/local/Cellar/arm-none-eabi-gcc/9-2019-q4-major/gcc/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld: cannot open linker script file build/objfw/script.ld: No such file or directory

It seems script.ld is not being generated.
Any insight you can give would be greatly appreciated. Thanks.

Error "sorry - this program has been built without plugin support"

Hi Dmitry,

I am trying to compile this for STM32F070CB. make stm32f070xb command gives me /bin/sh: del: command not found make: *** [fwclean] Error 127 error.
If I type make bootloader stm32f070xb, it compiles everything until it starts to build usb module.
Error log is below:

building module usb
make[1]: Entering directory `/c/Users/cdev/Desktop/STM32_BL/usb'
/bin/sh: del: command not found
make[1]: *** [clean] Error 127
make[1]: Leaving directory `/c/Users/cdev/Desktop/STM32_BL/usb'
make: *** [build/objfw/libusb.a] Error 2 

I replaced

ifeq ($(OS),Windows_NT)
	RM = del /Q
	fixpath = $(strip $(subst /,\, $1))
else
	RM = rm -f
	fixpath = $(strip $1)
endif

with

RM = rm -f
fixpath = $(strip $1)

in both usb and main makefile.

Now I get this error.

C:\Users\cdev\Desktop\STM32_BL>make stm32f070xb
make bootloader FWCPU='-mcpu=cortex-m0' \
                           FWSTARTUP='mcu/stm32f0xx.S' \
                           FWDEFS='STM32F0 STM32F070xB USBD_ASM_DRIVER' \
                           LDPARAMS='ROMLEN=128K RAMLEN=16K'
make[1]: Entering directory `/c/Users/cdev/Desktop/STM32_BL'
compiling src/arc4.c
compiling src/chacha.c
compiling src/gost.c
compiling src/raiden.c
compiling src/rc5.c
compiling src/speck.c
compiling src/xtea.c
compiling src/xtea1.c
compiling src/blowfish.c
compiling src/rtea.c
compiling src/rc6.c
compiling src/rijndael.c
compiling src/magma.c
compiling src/checksum.c
compiling src/crypto.c
assembling mcu/stm32f0xx.S
compiling src/descriptors.c
In file included from usb/inc/usb.h:22:0,
                 from src/descriptors.c:21:
usb/inc/usbd_core.h:38:1: warning: "/*" within comment [-Wcomment]
compiling src/bootloader.c
In file included from usb/inc/usb.h:22:0,
                 from src/bootloader.c:21:
usb/inc/usbd_core.h:38:1: warning: "/*" within comment [-Wcomment]
assembling src/rc5a.S
assembling src/chacha_a.S
assembling src/rc6a.S
building module usb
make[2]: Entering directory `/c/Users/cdev/Desktop/STM32_BL/usb'
make /c/Users/cdev/Desktop/STM32_BL/build/objfw/libusb.a
make[3]: Entering directory `/c/Users/cdev/Desktop/STM32_BL/usb'
compiling src/usbd_core.c
compiling src/usbd_stm32f103_devfs.c
compiling src/usbd_stm32f105_otgfs.c
compiling src/usbd_stm32f429_otgfs.c
compiling src/usbd_stm32f429_otghs.c
compiling src/usbd_stm32f446_otgfs.c
compiling src/usbd_stm32f446_otghs.c
compiling src/usbd_stm32l052_devfs.c
src/usbd_stm32l052_devfs.c:24:13: note: #pragma message: PMA memory size is not defined. Use 1k by default
compiling src/usbd_stm32l100_devfs.c
compiling src/usbd_stm32l433_devfs.c
compiling src/usbd_stm32l476_otgfs.c
assembling src/usbd_stm32f103_devfs_asm.S
assembling src/usbd_stm32l052_devfs_asm.S
assembling src/usbd_stm32l100_devfs_asm.S
sorry - this program has been built without plugin support
make[3]: *** [/c/Users/cdev/Desktop/STM32_BL/build/objfw/libusb.a] Error 24
make[3]: Leaving directory `/c/Users/cdev/Desktop/STM32_BL/usb'
make[2]: *** [module] Error 2
make[2]: Leaving directory `/c/Users/cdev/Desktop/STM32_BL/usb'
make[1]: *** [build/objfw/libusb.a] Error 2
make[1]: Leaving directory `/c/Users/cdev/Desktop/STM32_BL'
make: *** [stm32f070xb] Error 2

Can you help me with this please? Also I tried to import this to a Atollic TrueSTUDIO or STM32cubeIDE. Didn’t managed to do it properly. I am new to this. Recently transitioned from Arduino IDE. Can you guide me to import this to an IDE? Thanks for your time.

Use HSI48+CRS on L0

It is rather a happy accident (not guaranteed by spec) that the L0 USB works off of the HSI16 like we use it. On the L0 the crystal-less USB should use the HSI48 with the Clock Recovery System. I may get around to doing it soon but as a documentation note, this would be the presumed init sequence:

  1. Enable HSI48 voltage reference thing SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48;
  2. Enable HSI48
  3. Enable CRS clock RCC->APB1ENR |= RCC_APB1ENR_CRSEN;
  4. Enable CRS with default parameters CRS->CR |= CRS_CR_AUTOTRIMEN | CRS_CR_CEN;

Don't know if some other family is also affected (L1 ??)

refactoring of encryption commands

I think it makes sense to refactor the encryption, currently the software uses aes_init aes_encrypt etc as function names regardless of whether aes encryption is used, it might actually be blowfish or something else that is actually being used.

Something like the following might give the code a bit more clarity:

eal_init
eal_encrypt
eal_decrypt

(Encryption Abstraction Layer)

It's just a thought and something that's been bugging me in the back of my mind for months, the whole project is very well written and this "misnaming" (probably for historical reasons) just doesn't seem in keeping with your own high standards.

I know it's a minor thing and it makes no difference to functionality, but I personally think it will bring an improvement to the code base.

User firmware stuck or not starting after reset.

I have a demo firmware toggling 6 LEDs in sequence. I uploaded it using dfu-util but it does not start. First LED turns on and it stops there. I'm guessing that I forgot to add something in my code. DFU_APP_START is set to 0x08001000 and DFU_APP_SIZE is set to 126976 in config file. Also I set FLASH (rx) : ORIGIN = 0x08001000, LENGTH = 124K in my demo project. I've uploaded my demo project along with bootloader.map and config.h file to Google Drive. Can you check if something is wrong?

https://drive.google.com/drive/folders/17VR4t5-j2v8Tgzqlx1nVWkIIFzimskdh?usp=sharing

stm32.h

Dmitry,
It seems that the header "stm32.h" is missing
Cheers,
Kirill

Generating empty elf in openstm32 - system workbench

Dear Admin,

Came across the project and tried to implement on stm32f042x6 connected to macos catalina with SystemWorkbench IDE.
However I got below error message during compilation.

Applications/Xcode.app/Contents/Developer/usr/bin/make -f ldscript.mk ROMLEN=32K RAMLEN=6K OUTFILE=build/objfw/script.ld
Building linker script
building bootloader
text data bss dec hex filename
0 0 0 0 0 build/firmware.elf
creating build/firmware.hex
arm-none-eabi-objcopy: error: the input file 'build/firmware.elf' has no sections
make[1]: *** [build/firmware.hex] Error 1
make: *** [stm32f042x6] Error 2

I thought it was due to my minor modification but it was not. I tried those mentioned "tested" board and got the same error message.

Last to mention, I also made modification to the linker script. It is in the last few lines of the ldscript.mk as.
Mine is,

PHONY: all $(OUTFILE)

all: $(OUTFILE)
	$(file >> $<,$(LDSCRIPT))

$(OUTFILE):
	@echo Building linker script
	@echo '/* This file is automatically generated */' > $@

The above is the previous version as the latest version will trigger another error:

file script.Id cannot be found

Hope someone may take a look. Thank you very much.

Can't upload

Hello,
After lot's of pain, I succeded to make the bin file for the bootloader.
I flash the memory and the STM32F103C8 is recognized as a STM DFU. To test I don't use the encrytpion yet.
I remap the user programm to 0x08001000, compile with latest version of arduino ide. Download via DFU is not possible via Arduino. simple blink example led on PB13 and PC13
If I flash via DFU-Util on C:\dfu-util with admin right, the blink programm does not start at all. Any idea?
COuld you provide a blink.bin to test the download with your file at least to test if the bootload operates correctly. I supect an error in my link file, but where ???
What should be done or use to compile all correctly?

User code in bootloader

What is the "correct" procedure for injecting user code into the bootloader? For example I want to display some content on the display while the device is in DFU.

One solution might be adding user_init and user_poll to the existing main:

dfu_init();
user_init(); ///
while(1) {
    usbd_poll(&dfu);
    user_poll(); ///
}

Another solution might be to allow disabling the default main (and then calling dfu/usbd from user source:

#ifndef DFU_CUSTOM_MAIN
dfu_init();
while(1) {
    usbd_poll(&dfu);
}
#endif

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.