Adds RSA support to wolfBoot using "SIGN=RSA2048". Includes RSA signing script tool in Python and instructions.

pull/26/head
David Garske 2019-12-06 06:33:47 -08:00
parent dc4ea1975d
commit fae6a974c8
19 changed files with 363 additions and 69 deletions

1
.gitignore vendored
View File

@ -52,6 +52,7 @@
# automatically generated source files # automatically generated source files
src/ed25519_pub_key.c src/ed25519_pub_key.c
src/ecc256_pub_key.c src/ecc256_pub_key.c
src/rsa2048_pub_key.c
# keygen binaries # keygen binaries
tools/ed25519/ed25519_sign tools/ed25519/ed25519_sign

View File

@ -8,7 +8,7 @@
include tools/config.mk include tools/config.mk
## Initializers ## Initializers
CFLAGS:=-D__WOLFBOOT -DWOLFBOOT_VERSION=$(WOLFBOOT_VERSION)UL -ffunction-sections -fdata-sections CFLAGS:=-D__WOLFBOOT -DWOLFBOOT_VERSION=$(WOLFBOOT_VERSION)UL -ffunction-sections -fdata-sections
LSCRIPT:=config/target.ld LSCRIPT:=config/target.ld
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles
OBJS:= \ OBJS:= \
@ -16,19 +16,13 @@ OBJS:= \
./src/loader.o \ ./src/loader.o \
./src/string.o \ ./src/string.o \
./src/image.o \ ./src/image.o \
./src/libwolfboot.o \ ./src/libwolfboot.o
./lib/wolfssl/wolfcrypt/src/sha256.o \
./lib/wolfssl/wolfcrypt/src/hash.o \
./lib/wolfssl/wolfcrypt/src/wolfmath.o \
./lib/wolfssl/wolfcrypt/src/fe_low_mem.o
## Architecture/CPU configuration ## Architecture/CPU configuration
include arch.mk include arch.mk
## DSA Settings ## DSA Settings
ifeq ($(SIGN),ECC256) ifeq ($(SIGN),ECC256)
KEYGEN_OPTIONS=--ecc256 KEYGEN_OPTIONS=--ecc256
SIGN_OPTIONS=--ecc256 SIGN_OPTIONS=--ecc256
@ -37,26 +31,53 @@ ifeq ($(SIGN),ECC256)
$(ECC_EXTRA_OBJS) \ $(ECC_EXTRA_OBJS) \
$(MATH_OBJS) \ $(MATH_OBJS) \
./lib/wolfssl/wolfcrypt/src/ecc.o \ ./lib/wolfssl/wolfcrypt/src/ecc.o \
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
./lib/wolfssl/wolfcrypt/src/memory.o \ ./lib/wolfssl/wolfcrypt/src/memory.o \
./lib/wolfssl/wolfcrypt/src/wc_port.o \ ./lib/wolfssl/wolfcrypt/src/wc_port.o \
./lib/wolfssl/wolfcrypt/src/sha256.o \
./lib/wolfssl/wolfcrypt/src/hash.o \
./src/ecc256_pub_key.o \ ./src/ecc256_pub_key.o \
./src/xmalloc.o ./src/xmalloc_ecc.o
CFLAGS+=-DWOLFBOOT_SIGN_ECC256 -DXMALLOC_USER $(ECC_EXTRA_CFLAGS) CFLAGS+=-DWOLFBOOT_SIGN_ECC256 -DXMALLOC_USER $(ECC_EXTRA_CFLAGS) \
else -Wstack-usage=1024
endif
ifeq ($(SIGN),ED25519)
KEYGEN_OPTIONS=--ed25519 KEYGEN_OPTIONS=--ed25519
SIGN_OPTIONS=--ed25519 SIGN_OPTIONS=--ed25519
PRIVATE_KEY=ed25519.der PRIVATE_KEY=ed25519.der
OBJS+= ./lib/wolfssl/wolfcrypt/src/sha512.o \ OBJS+= ./lib/wolfssl/wolfcrypt/src/sha512.o \
./lib/wolfssl/wolfcrypt/src/ed25519.o \ ./lib/wolfssl/wolfcrypt/src/ed25519.o \
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \ ./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
./lib/wolfssl/wolfcrypt/src/sha256.o \
./lib/wolfssl/wolfcrypt/src/hash.o \
./lib/wolfssl/wolfcrypt/src/wolfmath.o \
./lib/wolfssl/wolfcrypt/src/fe_low_mem.o \
./src/ed25519_pub_key.o ./src/ed25519_pub_key.o
CFLAGS+=-DWOLFBOOT_SIGN_ED25519 -nostdlib -DWOLFSSL_STATIC_MEMORY CFLAGS+=-DWOLFBOOT_SIGN_ED25519 -nostdlib -DWOLFSSL_STATIC_MEMORY \
-Wstack-usage=1024
LDFLAGS+=-nostdlib LDFLAGS+=-nostdlib
endif endif
ifeq ($(SIGN),RSA2048)
KEYGEN_OPTIONS=--rsa2048
SIGN_OPTIONS=--rsa2048
PRIVATE_KEY=rsa2048.der
IMAGE_HEADER_SIZE=512
OBJS+= \
$(RSA_EXTRA_OBJS) \
$(MATH_OBJS) \
./lib/wolfssl/wolfcrypt/src/rsa.o \
./lib/wolfssl/wolfcrypt/src/sha256.o \
./lib/wolfssl/wolfcrypt/src/asn.o \
./lib/wolfssl/wolfcrypt/src/hash.o \
./src/rsa2048_pub_key.o \
./src/xmalloc_rsa.o
CFLAGS+=-DWOLFBOOT_SIGN_RSA2048 -DXMALLOC_USER $(RSA_EXTRA_CFLAGS) \
-Wstack-usage=4096 -DIMAGE_HEADER_SIZE=512
endif
CFLAGS+=-Wall -Wextra -Wno-main -Wstack-usage=1024 -ffreestanding -Wno-unused \
CFLAGS+=-Wall -Wextra -Wno-main -ffreestanding -Wno-unused \
-I. -Iinclude/ -Ilib/wolfssl -nostartfiles \ -I. -Iinclude/ -Ilib/wolfssl -nostartfiles \
-DWOLFSSL_USER_SETTINGS \ -DWOLFSSL_USER_SETTINGS \
-DPLATFORM_$(TARGET) -DPLATFORM_$(TARGET)
@ -108,15 +129,15 @@ ASFLAGS:=$(CFLAGS)
all: factory.bin all: factory.bin
wolfboot.bin: wolfboot.elf wolfboot.bin: wolfboot.elf
@echo "\t[BIN] $@" @echo "\t[BIN] $@"
$(Q)$(OBJCOPY) -O binary $^ $@ $(Q)$(OBJCOPY) -O binary $^ $@
wolfboot.hex: wolfboot.elf wolfboot.hex: wolfboot.elf
@echo "\t[HEX] $@" @echo "\t[HEX] $@"
$(Q)$(OBJCOPY) -O ihex $^ $@ $(Q)$(OBJCOPY) -O ihex $^ $@
align: wolfboot-align.bin align: wolfboot-align.bin
.bootloader-partition-size: FORCE .bootloader-partition-size: FORCE
@printf "%d" $(WOLFBOOT_PARTITION_BOOT_ADDRESS) > .wolfboot-offset @printf "%d" $(WOLFBOOT_PARTITION_BOOT_ADDRESS) > .wolfboot-offset
@printf "%d" $(ARCH_FLASH_OFFSET) > .wolfboot-arch-offset @printf "%d" $(ARCH_FLASH_OFFSET) > .wolfboot-arch-offset
@ -136,6 +157,15 @@ test-app/image.bin: wolfboot-align.bin
@rm -f src/*.o hal/*.o @rm -f src/*.o hal/*.o
@$(SIZE) test-app/image.elf @$(SIZE) test-app/image.elf
standalone:
@make -C test-app TARGET=$(TARGET) EXT_FLASH=$(EXT_FLASH) SPI_FLASH=$(SPI_FLASH) ARCH=$(ARCH) \
V=$(V) RAM_CODE=$(RAM_CODE) WOLFBOOT_VERSION=$(WOLFBOOT_VERSION)\
KINETIS=$(KINETIS) KINETIS_CPU=$(KINETIS_CPU) KINETIS_DRIVERS=$(KINETIS_DRIVERS) \
KINETIS_CMSIS=$(KINETIS_CMSIS) NVM_FLASH_WRITEONCE=$(NVM_FLASH_WRITEONCE) \
FREEDOM_E_SDK=$(FREEDOM_E_SDK) standalone
$(Q)$(OBJCOPY) -O binary test-app/image.elf standalone.bin
@$(SIZE) test-app/image.elf
include tools/test.mk include tools/test.mk
ed25519.der: ed25519.der:
@ -144,6 +174,9 @@ ed25519.der:
ecc256.der: ecc256.der:
@python3 tools/keytools/keygen.py $(KEYGEN_OPTIONS) src/ecc256_pub_key.c @python3 tools/keytools/keygen.py $(KEYGEN_OPTIONS) src/ecc256_pub_key.c
rsa2048.der:
@python3 tools/keytools/keygen.py $(KEYGEN_OPTIONS) src/rsa2048_pub_key.c
factory.bin: $(BOOT_IMG) wolfboot-align.bin $(PRIVATE_KEY) factory.bin: $(BOOT_IMG) wolfboot-align.bin $(PRIVATE_KEY)
@echo "\t[SIGN] $(BOOT_IMG)" @echo "\t[SIGN] $(BOOT_IMG)"
$(Q)python3 tools/keytools/sign.py $(SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) 1 $(Q)python3 tools/keytools/sign.py $(SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) 1
@ -163,15 +196,17 @@ src/ed25519_pub_key.c: ed25519.der
src/ecc256_pub_key.c: ecc256.der src/ecc256_pub_key.c: ecc256.der
src/rsa2048_pub_key.c: rsa2048.der
keys: $(PRIVATE_KEY) keys: $(PRIVATE_KEY)
clean: clean:
@find . -type f -name "*.o" | xargs rm -f @find . -type f -name "*.o" | xargs rm -f
@rm -f *.bin *.elf wolfboot.map *.bin *.hex config/target.ld @rm -f *.bin *.elf wolfboot.map *.bin *.hex config/target.ld
@make -C test-app clean @make -C test-app clean
distclean: clean distclean: clean
@rm -f *.pem *.der tags ./src/ed25519_pub_key.c ./src/ecc256_pub_key.c include/target.h @rm -f *.pem *.der tags ./src/ed25519_pub_key.c ./src/ecc256_pub_key.c ./src/rsa2048_pub_key.c include/target.h
include/target.h: include/target.h.in FORCE include/target.h: include/target.h.in FORCE
@cat include/target.h.in | \ @cat include/target.h.in | \
@ -193,6 +228,6 @@ config: FORCE
@echo "\t[AS-$(ARCH)] $@" @echo "\t[AS-$(ARCH)] $@"
$(Q)$(CC) $(CFLAGS) -c -o $@ $^ $(Q)$(CC) $(CFLAGS) -c -o $@ $^
FORCE: FORCE:
.PHONY: FORCE clean .PHONY: FORCE clean

View File

@ -1,7 +1,7 @@
# wolfBoot # wolfBoot
wolfSSL Secure Bootloader ([Home page](https://www.wolfssl.com/products/wolfboot/)) wolfSSL Secure Bootloader ([Home page](https://www.wolfssl.com/products/wolfboot/))
wolfBoot is a portable, OS-agnostic, secure bootloader solution for 32-bit microcontrollers, wolfBoot is a portable, OS-agnostic, secure bootloader solution for 32-bit microcontrollers,
relying on wolfCrypt for firmware authentication, providing firmware update mechanisms. relying on wolfCrypt for firmware authentication, providing firmware update mechanisms.
Due to the minimalist design of the bootloader and the tiny HAL API, wolfBoot is completely independent Due to the minimalist design of the bootloader and the tiny HAL API, wolfBoot is completely independent
@ -21,8 +21,8 @@ projects to provide a secure firmware update mechanism.
This repository contains the following components: This repository contains the following components:
- the wolfBoot bootloader - the wolfBoot bootloader
- key generator and image signing tools (requires python 3.x) - key generator and image signing tools (requires python 3.x and wolfcrypt-py https://github.com/wolfSSL/wolfcrypt-py)
- Baremetal test applications - Baremetal test applications
### wolfBoot bootloader ### wolfBoot bootloader
@ -32,7 +32,7 @@ with no dynamic memory allocation mechanism or linkage to any standard C library
The bootloader consists of the following components: The bootloader consists of the following components:
- wolfCrypt, which is used to verify the signature of the images - wolfCrypt, which is used to verify the signature of the images
- A minimalist Hardware Abstraction Layer, with an implementation provided for the supported target, which is in charge for IAP flash access and clock setting on the specific MCU - A minimalist Hardware Abstraction Layer, with an implementation provided for the supported target, which is in charge for IAP flash access and clock setting on the specific MCU
- The core bootloader - The core bootloader
- A small application library used by the application to interact with the bootloader [src/libwolfboot.c](src/libwolfboot.c) - A small application library used by the application to interact with the bootloader [src/libwolfboot.c](src/libwolfboot.c)
Only ARM Cortex-M boot mechanism is supported at this stage. Support for more architectures and Only ARM Cortex-M boot mechanism is supported at this stage. Support for more architectures and
@ -83,10 +83,48 @@ For detailed information about the configuration options for the target system,
For more detailed information about firmware update implementation, see [Firmware Update](docs/firmware_update.md) For more detailed information about firmware update implementation, see [Firmware Update](docs/firmware_update.md)
## Troubleshooting
1. Python errors when signing a key:
```
Traceback (most recent call last):
File "tools/keytools/keygen.py", line 135, in <module>
rsa = ciphers.RsaPrivate.make_key(2048)
AttributeError: type object 'RsaPrivate' has no attribute 'make_key'
```
```
Traceback (most recent call last):
File "tools/keytools/sign.py", line 189, in <module>
r, s = ecc.sign_raw(digest)
AttributeError: 'EccPrivate' object has no attribute 'sign_raw'
```
You need to install the latest wolfcrypt-pi here: https://github.com/wolfSSL/wolfcrypt-py
Use `pip3 install wolfcrypt`.
Make sure the wolfSSL library has been built with:
```sh
```
To install based on a local wolfSSL installation use:
```sh
cd youwolfssldir
./configure --enable-keygen --enable-rsa --enable-ecc --enable-ed25519 CFLAGS="-DWOLFSSL_PUBLIC_MP"
make
sudo make install
cd yourwolfcryptpydir
USE_LOCAL_WOLFSSL=/usr/local pip3 install .
```
## Release Notes ## Release Notes
### v1.0 (2018-12-04) ### v1.0 (2018-12-04)
* Initial release with fail-safe update, HAL support for STM32 and nRF52 * Initial release with fail-safe update, HAL support for STM32 and nRF52
### V1.1 (2019-03-27) ### V1.1 (2019-03-27)
* Added support for ECC-256 DSA * Added support for ECC-256 DSA

View File

@ -15,6 +15,11 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
_end_text = .; _end_text = .;
} > FLASH } > FLASH
.edidx :
{
. = ALIGN(4);
*(.ARM.exidx*)
} > FLASH
.edidx : .edidx :
{ {

44
hal/stm32l5.ld 100644
View File

@ -0,0 +1,44 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x001FFE0
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000
}
SECTIONS
{
.text :
{
_start_text = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
. = ALIGN(4);
_end_text = .;
} > FLASH
_stored_data = .;
.data : AT (_stored_data)
{
_start_data = .;
KEEP(*(.data*))
. = ALIGN(4);
KEEP(*(.ramcode))
. = ALIGN(4);
_end_data = .;
} > RAM
.bss (NOLOAD) :
{
_start_bss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_end_bss = .;
__bss_end__ = .;
_end = .;
} > RAM
. = ALIGN(4);
}
END_STACK = ORIGIN(RAM) + LENGTH(RAM);

View File

@ -15,7 +15,6 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
_end_text = .; _end_text = .;
} > FLASH } > FLASH
.edidx : .edidx :
{ {
. = ALIGN(4); . = ALIGN(4);

View File

@ -70,7 +70,7 @@ int wolfBoot_get_partition_state(uint8_t part, uint8_t *st);
int wolfBoot_get_sector_flag(uint8_t part, uint8_t sector, uint8_t *flag); int wolfBoot_get_sector_flag(uint8_t part, uint8_t sector, uint8_t *flag);
/* Defined in libwolfboot */ /* Defined in libwolfboot */
uint8_t wolfBoot_find_header(uint8_t *haystack, uint8_t type, uint8_t **ptr); uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr);
#ifdef EXT_FLASH #ifdef EXT_FLASH
# ifdef PART_UPDATE_EXT # ifdef PART_UPDATE_EXT

View File

@ -37,6 +37,12 @@
# define KEY_BUFFER ecc256_pub_key # define KEY_BUFFER ecc256_pub_key
# define KEY_LEN ecc256_pub_key_len # define KEY_LEN ecc256_pub_key_len
# define IMAGE_SIGNATURE_SIZE (64) # define IMAGE_SIGNATURE_SIZE (64)
#elif defined(WOLFBOOT_SIGN_RSA2048)
extern const unsigned char rsa2048_pub_key[];
extern unsigned int rsa2048_pub_key_len;
# define KEY_BUFFER rsa2048_pub_key
# define KEY_LEN rsa2048_pub_key_len
# define IMAGE_SIGNATURE_SIZE (256)
#else #else
# error "No public key available for given signing algorithm." # error "No public key available for given signing algorithm."
#endif /* Algorithm selection */ #endif /* Algorithm selection */

View File

@ -41,6 +41,8 @@
# define NO_ED25519_EXPORT # define NO_ED25519_EXPORT
# define WOLFSSL_SHA512 # define WOLFSSL_SHA512
# define USE_SLOW_SHA512 # define USE_SLOW_SHA512
# define NO_RSA
# define NO_ASN
#endif #endif
/* ECC and SHA256 */ /* ECC and SHA256 */
@ -78,15 +80,29 @@
# define NO_ECC224 # define NO_ECC224
# define HAVE_ECC256 # define HAVE_ECC256
# define NO_ECC384 # define NO_ECC384
# define NO_RSA
# define NO_ASN
#endif
#ifdef WOLFBOOT_SIGN_RSA2048
# define HAVE_RSA
# define RSA_LOW_MEM
# define WOLFSSL_STATIC_RSA
# define WOLFSSL_RSA_VERIFY_INLINE
//# define WOLFSSL_RSA_PUBLIC_ONLY
//# define WOLFSSL_RSA_VERIFY_ONLY
# define WOLFSSL_HAVE_SP_RSA
# define WOLFSSL_SP
# define WOLFSSL_SP_SMALL
# define WOLFSSL_SP_MATH
# define SP_WORD_SIZE 32
#endif #endif
/* Disables - For minimum wolfCrypt build */ /* Disables - For minimum wolfCrypt build */
#define NO_AES #define NO_AES
#define NO_CMAC #define NO_CMAC
#define NO_CODING #define NO_CODING
#define NO_RSA
#define NO_BIG_INT #define NO_BIG_INT
#define NO_ASN
#define NO_RC4 #define NO_RC4
#define NO_SHA #define NO_SHA
#define NO_DH #define NO_DH

View File

@ -28,7 +28,10 @@
#include <stdint.h> #include <stdint.h>
#include "target.h" #include "target.h"
#define IMAGE_HEADER_SIZE 256
#ifndef IMAGE_HEADER_SIZE
# define IMAGE_HEADER_SIZE 256
#endif
#define IMAGE_HEADER_OFFSET (2 * sizeof(uint32_t)) #define IMAGE_HEADER_OFFSET (2 * sizeof(uint32_t))
#define WOLFBOOT_MAGIC 0x464C4F57 /* WOLF */ #define WOLFBOOT_MAGIC 0x464C4F57 /* WOLF */
@ -45,6 +48,7 @@
#define HDR_IMG_TYPE_AUTH_ED25519 0x0100 #define HDR_IMG_TYPE_AUTH_ED25519 0x0100
#define HDR_IMG_TYPE_AUTH_ECC256 0x0200 #define HDR_IMG_TYPE_AUTH_ECC256 0x0200
#define HDR_IMG_TYPE_AUTH_RSA2048 0x0300
#define HDR_IMG_TYPE_WOLFBOOT 0x0000 #define HDR_IMG_TYPE_WOLFBOOT 0x0000
#define HDR_IMG_TYPE_APP 0x0001 #define HDR_IMG_TYPE_APP 0x0001
@ -54,8 +58,10 @@
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ED25519 # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ED25519
#elif defined(WOLFBOOT_SIGN_ECC256) #elif defined(WOLFBOOT_SIGN_ECC256)
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ECC256 # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ECC256
#elif defined(WOLFBOOT_SIGN_RSA2048)
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSA2048
#else #else
# error "no valid authentication mechanism selected. Please define WOLFBOOT_SIGN_ED25519 or WOLFBOOT_SIGN_ECC256" # error "no valid authentication mechanism selected. Please define WOLFBOOT_SIGN_ED25519 or WOLFBOOT_SIGN_ECC256 or WOLFBOOT_SIGN_RSA2048"
#endif /* defined WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ED25519 */ #endif /* defined WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ED25519 */
#endif /* defined WOLFBOOT */ #endif /* defined WOLFBOOT */

@ -1 +1 @@
Subproject commit 0fe5d40507e42945d5bc9aefb653ebb0b9f32cf3 Subproject commit 9fd56281482bac15de56269e68162b26f2fab6e7

View File

@ -86,9 +86,43 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
} }
#endif /* WOLFBOOT_SIGN_ECC256 */ #endif /* WOLFBOOT_SIGN_ECC256 */
static uint8_t get_header_ext(struct wolfBoot_image *img, uint8_t type, uint8_t **ptr); #ifdef WOLFBOOT_SIGN_RSA2048
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#define RSA_MAX_KEY_SIZE 256
#define RSA_SIG_SIZE 256
static uint8_t get_header(struct wolfBoot_image *img, uint8_t type, uint8_t **ptr) static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
{
int ret, res = 0;
struct RsaKey rsa;
uint8_t digest_out[IMAGE_SIGNATURE_SIZE];
word32 in_out = 0;
ret = wc_InitRsaKey(&rsa, NULL);
if (ret < 0) {
/* Failed to initialize key */
return -1;
}
/* Import public key */
ret = wc_RsaPublicKeyDecode((byte*)KEY_BUFFER, &in_out, &rsa, KEY_LEN);
if (ret < 0) {
/* Failed to import rsa key */
return -1;
}
ret = wc_RsaSSL_Verify(sig, RSA_SIG_SIZE, digest_out, RSA_SIG_SIZE, &rsa);
if (ret == SHA256_DIGEST_SIZE) {
if (memcmp(digest_out, hash, ret) == 0)
return 0;
}
return -1;
}
#endif /* WOLFBOOT_SIGN_RSA2048 */
static uint8_t get_header_ext(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr);
static uint16_t get_header(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr)
{ {
#if defined(PART_UPDATE_EXT) #if defined(PART_UPDATE_EXT)
if(img->part == PART_UPDATE) if(img->part == PART_UPDATE)
@ -128,7 +162,7 @@ static uint8_t *fetch_hdr_cpy(struct wolfBoot_image *img)
return hdr_cpy; return hdr_cpy;
} }
static uint8_t get_header_ext(struct wolfBoot_image *img, uint8_t type, uint8_t **ptr) static uint16_t get_header_ext(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr)
{ {
return wolfBoot_find_header(fetch_hdr_cpy(img) + IMAGE_HEADER_OFFSET, type, ptr); return wolfBoot_find_header(fetch_hdr_cpy(img) + IMAGE_HEADER_OFFSET, type, ptr);
} }
@ -148,7 +182,7 @@ static uint8_t *get_img_hdr(struct wolfBoot_image *img)
static int image_hash(struct wolfBoot_image *img, uint8_t *hash) static int image_hash(struct wolfBoot_image *img, uint8_t *hash)
{ {
uint8_t *stored_sha, *end_sha; uint8_t *stored_sha, *end_sha;
uint8_t stored_sha_len; uint16_t stored_sha_len;
uint8_t *p; uint8_t *p;
int blksz; int blksz;
uint32_t position = 0; uint32_t position = 0;
@ -160,7 +194,7 @@ static int image_hash(struct wolfBoot_image *img, uint8_t *hash)
if (stored_sha_len != SHA256_DIGEST_SIZE) if (stored_sha_len != SHA256_DIGEST_SIZE)
return -1; return -1;
wc_InitSha256(&sha256_ctx); wc_InitSha256(&sha256_ctx);
end_sha = stored_sha - 2; end_sha = stored_sha - 4;
while (p < end_sha) { while (p < end_sha) {
blksz = SHA256_BLOCK_SIZE; blksz = SHA256_BLOCK_SIZE;
if (end_sha - p < blksz) if (end_sha - p < blksz)
@ -248,7 +282,7 @@ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part)
int wolfBoot_verify_integrity(struct wolfBoot_image *img) int wolfBoot_verify_integrity(struct wolfBoot_image *img)
{ {
uint8_t *stored_sha; uint8_t *stored_sha;
uint8_t stored_sha_len; uint16_t stored_sha_len;
stored_sha_len = get_header(img, HDR_SHA256, &stored_sha); stored_sha_len = get_header(img, HDR_SHA256, &stored_sha);
if (stored_sha_len != SHA256_DIGEST_SIZE) if (stored_sha_len != SHA256_DIGEST_SIZE)
return -1; return -1;
@ -263,12 +297,12 @@ int wolfBoot_verify_integrity(struct wolfBoot_image *img)
int wolfBoot_verify_authenticity(struct wolfBoot_image *img) int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
{ {
uint8_t *stored_signature; uint8_t *stored_signature;
uint8_t stored_signature_size; uint16_t stored_signature_size;
uint8_t *pubkey_hint; uint8_t *pubkey_hint;
uint8_t pubkey_hint_size; uint16_t pubkey_hint_size;
uint8_t *image_type_buf; uint8_t *image_type_buf;
uint16_t image_type; uint16_t image_type;
uint8_t image_type_size; uint16_t image_type_size;
stored_signature_size = get_header(img, HDR_SIGNATURE, &stored_signature); stored_signature_size = get_header(img, HDR_SIGNATURE, &stored_signature);
if (stored_signature_size != IMAGE_SIGNATURE_SIZE) if (stored_signature_size != IMAGE_SIGNATURE_SIZE)

View File

@ -251,21 +251,21 @@ void RAMFUNCTION wolfBoot_success(void)
hal_flash_lock(); hal_flash_lock();
} }
uint8_t wolfBoot_find_header(uint8_t *haystack, uint8_t type, uint8_t **ptr) uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr)
{ {
uint8_t *p = haystack; uint8_t *p = haystack;
while (*p != 0) { uint16_t len;
while (((p[0] != 0) || (p[1] != 0)) && ((p - haystack) < IMAGE_HEADER_SIZE)) {
if (*p == HDR_PADDING) { if (*p == HDR_PADDING) {
p++; p++;
continue; continue;
} }
if (*p == type) { len = p[2] | (p[3] << 8);
p++; if ((p[0] | (p[1] << 8)) == type) {
*ptr = (p + 1); *ptr = (p + 4);
return *p; return len;
} }
p++; p += 4 + len;
p += (*p + 1);
} }
*ptr = NULL; *ptr = NULL;
return 0; return 0;

View File

@ -1,4 +1,4 @@
/* xmalloc.h /* xmalloc_ecc.c
* *
* Implementations of minimal malloc/free * Implementations of minimal malloc/free
* *

54
src/xmalloc_rsa.c 100644
View File

@ -0,0 +1,54 @@
/* xmalloc_rsa.c
*
* Implementations of minimal malloc/free
*
*
* Copyright (C) 2019 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdlib.h>
#include <stdint.h>
/* Allow one single sp_point to be allocated at one time */
#define SP_DIGIT_SIZE (1800)
static uint8_t sp_digit[SP_DIGIT_SIZE];
static int sp_digit_in_use = 0;
static void* xmalloc_sp_digit(void)
{
if (sp_digit_in_use)
return NULL;
sp_digit_in_use++;
return sp_digit;
}
void* XMALLOC(size_t n, void* heap, int type)
{
if (n == SP_DIGIT_SIZE)
return xmalloc_sp_digit();
return NULL;
}
void XFREE(void *ptr)
{
int i;
if (ptr == sp_digit)
sp_digit_in_use = 0;
}

View File

@ -61,7 +61,7 @@ void led_pwm_setup(void)
void boot_led_on(void) void boot_led_on(void)
{ {
uint32_t reg; uint32_t reg;
uint32_t pin = LED_BOOT_PIN - 2 * (wolfBoot_current_firmware_version() & 0x01); uint32_t pin = LED_BOOT_PIN;// - 2 * (wolfBoot_current_firmware_version() & 0x01);
AHB1_CLOCK_ER |= GPIOD_AHB1_CLOCK_ER; AHB1_CLOCK_ER |= GPIOD_AHB1_CLOCK_ER;
reg = GPIOD_MODE & ~(0x03 << (pin * 2)); reg = GPIOD_MODE & ~(0x03 << (pin * 2));
GPIOD_MODE = reg | (1 << (pin * 2)); GPIOD_MODE = reg | (1 << (pin * 2));

View File

@ -39,4 +39,3 @@ CONFIG_VARS:= ARCH TARGET SIGN KINETIS KINETIS_CPU KINETIS_DRIVERS \
WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE \ WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE \
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \ WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_PARTITION_SWAP_ADDRESS

View File

@ -33,6 +33,7 @@ Cfile_Banner="/* Public-key file for wolfBoot, automatically generated. Do not e
Ed25519_pub_key_define = "const uint8_t ed25519_pub_key[32] = {\n\t" Ed25519_pub_key_define = "const uint8_t ed25519_pub_key[32] = {\n\t"
Ecc256_pub_key_define = "const uint8_t ecc256_pub_key[64] = {\n\t" Ecc256_pub_key_define = "const uint8_t ecc256_pub_key[64] = {\n\t"
Rsa_pub_key_define = "const uint8_t rsa2048_pub_key[%d] = {\n\t"
sign="ed25519" sign="ed25519"
@ -40,12 +41,12 @@ argc = len(sys.argv)
argv = sys.argv argv = sys.argv
if (argc < 2) or (argc > 3): if (argc < 2) or (argc > 3):
print("Usage: %s [--ed25519 | --ecc256 ] pub_key_file.c\n" % sys.argv[0]) print("Usage: %s [--ed25519 | --ecc256 | --rsa2048 ] pub_key_file.c\n" % sys.argv[0])
sys.exit(1) sys.exit(1)
if argc == 3: if argc == 3:
if argv[1] != '--ed25519' and argv[1] != '--ecc256': if argv[1] != '--ed25519' and argv[1] != '--ecc256' and argv[1] != '--rsa2048':
print("Usage: %s [--ed25519 | --ecc256 ] pub_key_file.c\n" % sys.argv[0]) print("Usage: %s [--ed25519 | --ecc256 | --rsa2048] pub_key_file.c\n" % sys.argv[0])
sys.exit(1) sys.exit(1)
sign=argv[1][2:] sign=argv[1][2:]
pubkey_cfile = argv[2] pubkey_cfile = argv[2]
@ -130,3 +131,30 @@ if (sign == "ecc256"):
f.close() f.close()
if (sign == "rsa2048"):
rsa = ciphers.RsaPrivate.make_key(2048)
if os.path.exists(key_file):
choice = input("** Warning: key file already exist! Are you sure you want to "+
"generate a new key and overwrite the existing key? [Type 'Yes, I am sure!']: ")
if (choice != "Yes, I am sure!"):
print("Operation canceled.")
sys.exit(2)
priv,pub = rsa.encode_key()
print()
print("Creating file " + key_file)
with open(key_file, "wb") as f:
f.write(priv)
f.close()
print("Creating file " + pubkey_cfile)
with open(pubkey_cfile, "w") as f:
f.write(Cfile_Banner)
f.write(Rsa_pub_key_define % len(pub))
i = 0
for c in bytes(pub):
f.write("0x%02X, " % c)
i += 1
if (i % 8 == 0):
f.write('\n')
f.write("\n};\n")
f.write("const uint32_t rsa2048_pub_key_len = %d;\n" % len(pub))
f.close()

View File

@ -45,10 +45,13 @@ HDR_SIGNATURE_LEN = 64
HDR_IMG_TYPE_AUTH_ED25519 = 0x0100 HDR_IMG_TYPE_AUTH_ED25519 = 0x0100
HDR_IMG_TYPE_AUTH_ECC256 = 0x0200 HDR_IMG_TYPE_AUTH_ECC256 = 0x0200
HDR_IMG_TYPE_AUTH_RSA2048 = 0x0300
HDR_IMG_TYPE_WOLFBOOT = 0x0000 HDR_IMG_TYPE_WOLFBOOT = 0x0000
HDR_IMG_TYPE_APP = 0x0001 HDR_IMG_TYPE_APP = 0x0001
WOLFBOOT_HEADER_SIZE = 256
sign="auto" sign="auto"
self_update=False self_update=False
@ -56,13 +59,15 @@ argc = len(sys.argv)
argv = sys.argv argv = sys.argv
if (argc < 4) or (argc > 6): if (argc < 4) or (argc > 6):
print("Usage: %s [--ed25519 | --ecc256 ] [--wolfboot-update] image key.der fw_version\n" % sys.argv[0]) print("Usage: %s [--ed25519 | --ecc256 | --rsa2048 ] [--wolfboot-update] image key.der fw_version\n" % sys.argv[0])
sys.exit(1) sys.exit(1)
for i in range(1, len(argv)): for i in range(1, len(argv)):
if (argv[i] == '--ed25519'): if (argv[i] == '--ed25519'):
sign='ed25519' sign='ed25519'
elif (argv[i] == '--ecc256'): elif (argv[i] == '--ecc256'):
sign='ecc256' sign='ecc256'
elif (argv[i] == '--rsa2048'):
sign='rsa2048'
elif (argv[i] == '--wolfboot-update'): elif (argv[i] == '--wolfboot-update'):
self_update = True self_update = True
else: else:
@ -93,7 +98,7 @@ print ("Output image: " + output_image_file)
''' import (decode) private key for signing ''' ''' import (decode) private key for signing '''
kf = open(key_file, "rb") kf = open(key_file, "rb")
wolfboot_private_key = kf.read(96) wolfboot_private_key = kf.read(4096)
wolfboot_private_key_len = len(wolfboot_private_key) wolfboot_private_key_len = len(wolfboot_private_key)
if wolfboot_private_key_len == 64: if wolfboot_private_key_len == 64:
if (sign == 'ecc256'): if (sign == 'ecc256'):
@ -109,6 +114,11 @@ elif wolfboot_private_key_len == 96:
if sign == 'auto': if sign == 'auto':
sign = 'ecc256' sign = 'ecc256'
print("'ecc256' key autodetected.") print("'ecc256' key autodetected.")
elif (wolfboot_private_key_len > 128):
if (sign == 'auto'):
print("'rsa2048' key autodetected.")
elif (sign != 'rsa2048'):
print ("Error: key size too large for the selected cipher")
else: else:
print ("Error: key size does not match any cipher") print ("Error: key size does not match any cipher")
sys.exit(2) sys.exit(2)
@ -123,6 +133,12 @@ if sign == 'ecc256':
ecc.decode_key_raw(wolfboot_private_key[0:31], wolfboot_private_key[32:63], wolfboot_private_key[64:]) ecc.decode_key_raw(wolfboot_private_key[0:31], wolfboot_private_key[32:63], wolfboot_private_key[64:])
pubkey = wolfboot_private_key[0:64] pubkey = wolfboot_private_key[0:64]
if sign == 'rsa2048':
WOLFBOOT_HEADER_SIZE = 512
HDR_SIGNATURE_LEN = 256
rsa = ciphers.RsaPrivate(wolfboot_private_key)
privkey,pubkey = rsa.encode_key()
img_size = os.path.getsize(image_file) img_size = os.path.getsize(image_file)
# Magic header (spells 'WOLF') # Magic header (spells 'WOLF')
@ -130,28 +146,28 @@ header = struct.pack('<L', WOLFBOOT_MAGIC)
# Image size # Image size
header += struct.pack('<L', img_size) header += struct.pack('<L', img_size)
# Two pad bytes so version is aligned # No pad bytes, version is aligned
header += struct.pack('BB', 0xFF, 0xFF)
# Version field # Version field
header += struct.pack('BB', HDR_VERSION, HDR_VERSION_LEN) header += struct.pack('<HH', HDR_VERSION, HDR_VERSION_LEN)
header += struct.pack('<L', fw_version) header += struct.pack('<L', fw_version)
# Six pad bytes so timestamp is aligned # Four pad bytes, so timestamp is aligned
header += struct.pack('BB', 0xFF, 0xFF)
header += struct.pack('BB', 0xFF, 0xFF) header += struct.pack('BB', 0xFF, 0xFF)
header += struct.pack('BB', 0xFF, 0xFF) header += struct.pack('BB', 0xFF, 0xFF)
# Timestamp field # Timestamp field
header += struct.pack('BB', HDR_TIMESTAMP, HDR_TIMESTAMP_LEN) header += struct.pack('<HH', HDR_TIMESTAMP, HDR_TIMESTAMP_LEN)
header += struct.pack('<Q', int(os.path.getmtime(image_file))) header += struct.pack('<Q', int(os.path.getmtime(image_file)))
# Image type field # Image type field
header += struct.pack('BB', HDR_IMG_TYPE, HDR_IMG_TYPE_LEN) header += struct.pack('<HH', HDR_IMG_TYPE, HDR_IMG_TYPE_LEN)
if (sign == 'ed25519'): if (sign == 'ed25519'):
img_type = HDR_IMG_TYPE_AUTH_ED25519 img_type = HDR_IMG_TYPE_AUTH_ED25519
if (sign == 'ecc256'): if (sign == 'ecc256'):
img_type = HDR_IMG_TYPE_AUTH_ECC256 img_type = HDR_IMG_TYPE_AUTH_ECC256
if (sign == 'rsa2048'):
img_type = HDR_IMG_TYPE_AUTH_RSA2048
if (not self_update): if (not self_update):
img_type |= HDR_IMG_TYPE_APP img_type |= HDR_IMG_TYPE_APP
@ -171,32 +187,45 @@ while True:
digest = sha.digest() digest = sha.digest()
# Add SHA to the header # Add SHA to the header
header += struct.pack('BB', HDR_SHA256, HDR_SHA256_LEN) header += struct.pack('<HH', HDR_SHA256, HDR_SHA256_LEN)
header += digest header += digest
#print("sha:")
#print([hex(j) for j in digest])
# pubkey SHA calculation # pubkey SHA calculation
#print([hex(j) for j in pubkey])
#print(len(pubkey))
keysha = hashes.Sha256.new() keysha = hashes.Sha256.new()
keysha.update(pubkey) keysha.update(pubkey)
header += struct.pack('BB', HDR_PUBKEY, HDR_PUBKEY_LEN)
key_digest = keysha.digest() key_digest = keysha.digest()
header += struct.pack('<HH', HDR_PUBKEY, HDR_PUBKEY_LEN)
header += key_digest header += key_digest
#print([hex(j) for j in key_digest])
# Sign the digest # Sign the digest
print("Signing the firmware...") print("Signing the firmware...")
if (sign == 'ed25519'): if (sign == 'ed25519'):
signature = ed.sign(digest) signature = ed.sign(digest)
else: elif (sign == 'ecc256'):
r, s = ecc.sign_raw(digest) r, s = ecc.sign_raw(digest)
signature = r + s signature = r + s
header += struct.pack('BB', HDR_SIGNATURE, HDR_SIGNATURE_LEN) elif (sign == 'rsa2048'):
signature = rsa.sign(digest)
#plain = rsa.verify(signature)
#print("plain:%d " % len(plain))
#print([hex(j) for j in plain])
header += struct.pack('<HH', HDR_SIGNATURE, HDR_SIGNATURE_LEN)
header += signature header += signature
#print ("len sig: %d\n" % len(signature))
#print([hex(j) for j in signature])
print ("Done.") print ("Done.")
# Create output image. Add padded header in front # Create output image. Add padded header in front
outfile = open(output_image_file, 'wb') outfile = open(output_image_file, 'wb')
outfile.write(header) outfile.write(header)
sz = len(header) sz = len(header)
while sz < 256: while sz < WOLFBOOT_HEADER_SIZE:
outfile.write(struct.pack('B',0xFF)) outfile.write(struct.pack('B',0xFF))
sz += 1 sz += 1
infile = open(image_file, 'rb') infile = open(image_file, 'rb')