mirror of https://github.com/wolfSSL/wolfBoot.git
Adds RSA support to wolfBoot using "SIGN=RSA2048". Includes RSA signing script tool in Python and instructions.
parent
dc4ea1975d
commit
fae6a974c8
|
@ -52,6 +52,7 @@
|
|||
# automatically generated source files
|
||||
src/ed25519_pub_key.c
|
||||
src/ecc256_pub_key.c
|
||||
src/rsa2048_pub_key.c
|
||||
|
||||
# keygen binaries
|
||||
tools/ed25519/ed25519_sign
|
||||
|
|
75
Makefile
75
Makefile
|
@ -8,7 +8,7 @@
|
|||
include tools/config.mk
|
||||
|
||||
## 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
|
||||
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles
|
||||
OBJS:= \
|
||||
|
@ -16,19 +16,13 @@ OBJS:= \
|
|||
./src/loader.o \
|
||||
./src/string.o \
|
||||
./src/image.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
|
||||
./src/libwolfboot.o
|
||||
|
||||
|
||||
## Architecture/CPU configuration
|
||||
include arch.mk
|
||||
|
||||
|
||||
## DSA Settings
|
||||
|
||||
ifeq ($(SIGN),ECC256)
|
||||
KEYGEN_OPTIONS=--ecc256
|
||||
SIGN_OPTIONS=--ecc256
|
||||
|
@ -37,26 +31,53 @@ ifeq ($(SIGN),ECC256)
|
|||
$(ECC_EXTRA_OBJS) \
|
||||
$(MATH_OBJS) \
|
||||
./lib/wolfssl/wolfcrypt/src/ecc.o \
|
||||
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
|
||||
./lib/wolfssl/wolfcrypt/src/memory.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/xmalloc.o
|
||||
CFLAGS+=-DWOLFBOOT_SIGN_ECC256 -DXMALLOC_USER $(ECC_EXTRA_CFLAGS)
|
||||
else
|
||||
./src/xmalloc_ecc.o
|
||||
CFLAGS+=-DWOLFBOOT_SIGN_ECC256 -DXMALLOC_USER $(ECC_EXTRA_CFLAGS) \
|
||||
-Wstack-usage=1024
|
||||
endif
|
||||
|
||||
ifeq ($(SIGN),ED25519)
|
||||
KEYGEN_OPTIONS=--ed25519
|
||||
SIGN_OPTIONS=--ed25519
|
||||
PRIVATE_KEY=ed25519.der
|
||||
OBJS+= ./lib/wolfssl/wolfcrypt/src/sha512.o \
|
||||
./lib/wolfssl/wolfcrypt/src/ed25519.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
|
||||
CFLAGS+=-DWOLFBOOT_SIGN_ED25519 -nostdlib -DWOLFSSL_STATIC_MEMORY
|
||||
CFLAGS+=-DWOLFBOOT_SIGN_ED25519 -nostdlib -DWOLFSSL_STATIC_MEMORY \
|
||||
-Wstack-usage=1024
|
||||
LDFLAGS+=-nostdlib
|
||||
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 \
|
||||
-DWOLFSSL_USER_SETTINGS \
|
||||
-DPLATFORM_$(TARGET)
|
||||
|
@ -108,15 +129,15 @@ ASFLAGS:=$(CFLAGS)
|
|||
all: factory.bin
|
||||
|
||||
wolfboot.bin: wolfboot.elf
|
||||
@echo "\t[BIN] $@"
|
||||
@echo "\t[BIN] $@"
|
||||
$(Q)$(OBJCOPY) -O binary $^ $@
|
||||
|
||||
wolfboot.hex: wolfboot.elf
|
||||
@echo "\t[HEX] $@"
|
||||
@echo "\t[HEX] $@"
|
||||
$(Q)$(OBJCOPY) -O ihex $^ $@
|
||||
|
||||
align: wolfboot-align.bin
|
||||
|
||||
|
||||
.bootloader-partition-size: FORCE
|
||||
@printf "%d" $(WOLFBOOT_PARTITION_BOOT_ADDRESS) > .wolfboot-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
|
||||
@$(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
|
||||
|
||||
ed25519.der:
|
||||
|
@ -144,6 +174,9 @@ ed25519.der:
|
|||
ecc256.der:
|
||||
@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)
|
||||
@echo "\t[SIGN] $(BOOT_IMG)"
|
||||
$(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/rsa2048_pub_key.c: rsa2048.der
|
||||
|
||||
keys: $(PRIVATE_KEY)
|
||||
|
||||
|
||||
clean:
|
||||
@find . -type f -name "*.o" | xargs rm -f
|
||||
@rm -f *.bin *.elf wolfboot.map *.bin *.hex config/target.ld
|
||||
@make -C test-app 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
|
||||
@cat include/target.h.in | \
|
||||
|
@ -193,6 +228,6 @@ config: FORCE
|
|||
@echo "\t[AS-$(ARCH)] $@"
|
||||
$(Q)$(CC) $(CFLAGS) -c -o $@ $^
|
||||
|
||||
FORCE:
|
||||
FORCE:
|
||||
|
||||
.PHONY: FORCE clean
|
||||
|
|
48
README.md
48
README.md
|
@ -1,7 +1,7 @@
|
|||
# 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.
|
||||
|
||||
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:
|
||||
- the wolfBoot bootloader
|
||||
- key generator and image signing tools (requires python 3.x)
|
||||
- Baremetal test applications
|
||||
- key generator and image signing tools (requires python 3.x and wolfcrypt-py https://github.com/wolfSSL/wolfcrypt-py)
|
||||
- Baremetal test applications
|
||||
|
||||
### 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:
|
||||
- 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
|
||||
- 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)
|
||||
|
||||
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)
|
||||
|
||||
## 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
|
||||
|
||||
### 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)
|
||||
* Added support for ECC-256 DSA
|
||||
|
|
|
@ -15,6 +15,11 @@ SECTIONS
|
|||
. = ALIGN(4);
|
||||
_end_text = .;
|
||||
} > FLASH
|
||||
.edidx :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.ARM.exidx*)
|
||||
} > FLASH
|
||||
|
||||
.edidx :
|
||||
{
|
||||
|
|
|
@ -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);
|
|
@ -15,7 +15,6 @@ SECTIONS
|
|||
. = ALIGN(4);
|
||||
_end_text = .;
|
||||
} > FLASH
|
||||
|
||||
.edidx :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* 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 PART_UPDATE_EXT
|
||||
|
|
|
@ -37,6 +37,12 @@
|
|||
# define KEY_BUFFER ecc256_pub_key
|
||||
# define KEY_LEN ecc256_pub_key_len
|
||||
# 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
|
||||
# error "No public key available for given signing algorithm."
|
||||
#endif /* Algorithm selection */
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
# define NO_ED25519_EXPORT
|
||||
# define WOLFSSL_SHA512
|
||||
# define USE_SLOW_SHA512
|
||||
# define NO_RSA
|
||||
# define NO_ASN
|
||||
#endif
|
||||
|
||||
/* ECC and SHA256 */
|
||||
|
@ -78,15 +80,29 @@
|
|||
# define NO_ECC224
|
||||
# define HAVE_ECC256
|
||||
# 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
|
||||
|
||||
/* Disables - For minimum wolfCrypt build */
|
||||
#define NO_AES
|
||||
#define NO_CMAC
|
||||
#define NO_CODING
|
||||
#define NO_RSA
|
||||
#define NO_BIG_INT
|
||||
#define NO_ASN
|
||||
#define NO_RC4
|
||||
#define NO_SHA
|
||||
#define NO_DH
|
||||
|
|
|
@ -28,7 +28,10 @@
|
|||
#include <stdint.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 WOLFBOOT_MAGIC 0x464C4F57 /* WOLF */
|
||||
|
@ -45,6 +48,7 @@
|
|||
|
||||
#define HDR_IMG_TYPE_AUTH_ED25519 0x0100
|
||||
#define HDR_IMG_TYPE_AUTH_ECC256 0x0200
|
||||
#define HDR_IMG_TYPE_AUTH_RSA2048 0x0300
|
||||
#define HDR_IMG_TYPE_WOLFBOOT 0x0000
|
||||
#define HDR_IMG_TYPE_APP 0x0001
|
||||
|
||||
|
@ -54,8 +58,10 @@
|
|||
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ED25519
|
||||
#elif defined(WOLFBOOT_SIGN_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
|
||||
# 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 */
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 0fe5d40507e42945d5bc9aefb653ebb0b9f32cf3
|
||||
Subproject commit 9fd56281482bac15de56269e68162b26f2fab6e7
|
52
src/image.c
52
src/image.c
|
@ -86,9 +86,43 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
|
|||
}
|
||||
#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(img->part == PART_UPDATE)
|
||||
|
@ -128,7 +162,7 @@ static uint8_t *fetch_hdr_cpy(struct wolfBoot_image *img)
|
|||
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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
uint8_t *stored_sha, *end_sha;
|
||||
uint8_t stored_sha_len;
|
||||
uint16_t stored_sha_len;
|
||||
uint8_t *p;
|
||||
int blksz;
|
||||
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)
|
||||
return -1;
|
||||
wc_InitSha256(&sha256_ctx);
|
||||
end_sha = stored_sha - 2;
|
||||
end_sha = stored_sha - 4;
|
||||
while (p < end_sha) {
|
||||
blksz = SHA256_BLOCK_SIZE;
|
||||
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)
|
||||
{
|
||||
uint8_t *stored_sha;
|
||||
uint8_t stored_sha_len;
|
||||
uint16_t stored_sha_len;
|
||||
stored_sha_len = get_header(img, HDR_SHA256, &stored_sha);
|
||||
if (stored_sha_len != SHA256_DIGEST_SIZE)
|
||||
return -1;
|
||||
|
@ -263,12 +297,12 @@ int wolfBoot_verify_integrity(struct wolfBoot_image *img)
|
|||
int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
|
||||
{
|
||||
uint8_t *stored_signature;
|
||||
uint8_t stored_signature_size;
|
||||
uint16_t stored_signature_size;
|
||||
uint8_t *pubkey_hint;
|
||||
uint8_t pubkey_hint_size;
|
||||
uint16_t pubkey_hint_size;
|
||||
uint8_t *image_type_buf;
|
||||
uint16_t image_type;
|
||||
uint8_t image_type_size;
|
||||
uint16_t image_type_size;
|
||||
|
||||
stored_signature_size = get_header(img, HDR_SIGNATURE, &stored_signature);
|
||||
if (stored_signature_size != IMAGE_SIGNATURE_SIZE)
|
||||
|
|
|
@ -251,21 +251,21 @@ void RAMFUNCTION wolfBoot_success(void)
|
|||
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;
|
||||
while (*p != 0) {
|
||||
uint16_t len;
|
||||
while (((p[0] != 0) || (p[1] != 0)) && ((p - haystack) < IMAGE_HEADER_SIZE)) {
|
||||
if (*p == HDR_PADDING) {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
if (*p == type) {
|
||||
p++;
|
||||
*ptr = (p + 1);
|
||||
return *p;
|
||||
len = p[2] | (p[3] << 8);
|
||||
if ((p[0] | (p[1] << 8)) == type) {
|
||||
*ptr = (p + 4);
|
||||
return len;
|
||||
}
|
||||
p++;
|
||||
p += (*p + 1);
|
||||
p += 4 + len;
|
||||
}
|
||||
*ptr = NULL;
|
||||
return 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* xmalloc.h
|
||||
/* xmalloc_ecc.c
|
||||
*
|
||||
* Implementations of minimal malloc/free
|
||||
*
|
|
@ -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;
|
||||
}
|
|
@ -61,7 +61,7 @@ void led_pwm_setup(void)
|
|||
void boot_led_on(void)
|
||||
{
|
||||
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;
|
||||
reg = GPIOD_MODE & ~(0x03 << (pin * 2));
|
||||
GPIOD_MODE = reg | (1 << (pin * 2));
|
||||
|
|
|
@ -39,4 +39,3 @@ CONFIG_VARS:= ARCH TARGET SIGN KINETIS KINETIS_CPU KINETIS_DRIVERS \
|
|||
WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE \
|
||||
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
|
||||
WOLFBOOT_PARTITION_SWAP_ADDRESS
|
||||
|
||||
|
|
|
@ -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"
|
||||
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"
|
||||
|
||||
|
@ -40,12 +41,12 @@ argc = len(sys.argv)
|
|||
argv = sys.argv
|
||||
|
||||
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)
|
||||
|
||||
if argc == 3:
|
||||
if argv[1] != '--ed25519' and argv[1] != '--ecc256':
|
||||
print("Usage: %s [--ed25519 | --ecc256 ] pub_key_file.c\n" % sys.argv[0])
|
||||
if argv[1] != '--ed25519' and argv[1] != '--ecc256' and argv[1] != '--rsa2048':
|
||||
print("Usage: %s [--ed25519 | --ecc256 | --rsa2048] pub_key_file.c\n" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
sign=argv[1][2:]
|
||||
pubkey_cfile = argv[2]
|
||||
|
@ -130,3 +131,30 @@ if (sign == "ecc256"):
|
|||
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()
|
||||
|
|
|
@ -45,10 +45,13 @@ HDR_SIGNATURE_LEN = 64
|
|||
|
||||
HDR_IMG_TYPE_AUTH_ED25519 = 0x0100
|
||||
HDR_IMG_TYPE_AUTH_ECC256 = 0x0200
|
||||
HDR_IMG_TYPE_AUTH_RSA2048 = 0x0300
|
||||
|
||||
HDR_IMG_TYPE_WOLFBOOT = 0x0000
|
||||
HDR_IMG_TYPE_APP = 0x0001
|
||||
|
||||
WOLFBOOT_HEADER_SIZE = 256
|
||||
|
||||
sign="auto"
|
||||
self_update=False
|
||||
|
||||
|
@ -56,13 +59,15 @@ argc = len(sys.argv)
|
|||
argv = sys.argv
|
||||
|
||||
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)
|
||||
for i in range(1, len(argv)):
|
||||
if (argv[i] == '--ed25519'):
|
||||
sign='ed25519'
|
||||
elif (argv[i] == '--ecc256'):
|
||||
sign='ecc256'
|
||||
elif (argv[i] == '--rsa2048'):
|
||||
sign='rsa2048'
|
||||
elif (argv[i] == '--wolfboot-update'):
|
||||
self_update = True
|
||||
else:
|
||||
|
@ -93,7 +98,7 @@ print ("Output image: " + output_image_file)
|
|||
|
||||
''' import (decode) private key for signing '''
|
||||
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)
|
||||
if wolfboot_private_key_len == 64:
|
||||
if (sign == 'ecc256'):
|
||||
|
@ -109,6 +114,11 @@ elif wolfboot_private_key_len == 96:
|
|||
if sign == 'auto':
|
||||
sign = 'ecc256'
|
||||
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:
|
||||
print ("Error: key size does not match any cipher")
|
||||
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:])
|
||||
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)
|
||||
# Magic header (spells 'WOLF')
|
||||
|
@ -130,28 +146,28 @@ header = struct.pack('<L', WOLFBOOT_MAGIC)
|
|||
# Image size
|
||||
header += struct.pack('<L', img_size)
|
||||
|
||||
# Two pad bytes so version is aligned
|
||||
header += struct.pack('BB', 0xFF, 0xFF)
|
||||
# No pad bytes, version is aligned
|
||||
|
||||
# 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)
|
||||
|
||||
# Six pad bytes so timestamp is aligned
|
||||
header += struct.pack('BB', 0xFF, 0xFF)
|
||||
# Four pad bytes, so timestamp is aligned
|
||||
header += struct.pack('BB', 0xFF, 0xFF)
|
||||
header += struct.pack('BB', 0xFF, 0xFF)
|
||||
|
||||
# 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)))
|
||||
|
||||
# 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'):
|
||||
img_type = HDR_IMG_TYPE_AUTH_ED25519
|
||||
if (sign == 'ecc256'):
|
||||
img_type = HDR_IMG_TYPE_AUTH_ECC256
|
||||
if (sign == 'rsa2048'):
|
||||
img_type = HDR_IMG_TYPE_AUTH_RSA2048
|
||||
|
||||
if (not self_update):
|
||||
img_type |= HDR_IMG_TYPE_APP
|
||||
|
@ -171,32 +187,45 @@ while True:
|
|||
digest = sha.digest()
|
||||
|
||||
# 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
|
||||
#print("sha:")
|
||||
#print([hex(j) for j in digest])
|
||||
|
||||
# pubkey SHA calculation
|
||||
#print([hex(j) for j in pubkey])
|
||||
#print(len(pubkey))
|
||||
keysha = hashes.Sha256.new()
|
||||
keysha.update(pubkey)
|
||||
header += struct.pack('BB', HDR_PUBKEY, HDR_PUBKEY_LEN)
|
||||
key_digest = keysha.digest()
|
||||
header += struct.pack('<HH', HDR_PUBKEY, HDR_PUBKEY_LEN)
|
||||
header += key_digest
|
||||
#print([hex(j) for j in key_digest])
|
||||
|
||||
# Sign the digest
|
||||
print("Signing the firmware...")
|
||||
if (sign == 'ed25519'):
|
||||
signature = ed.sign(digest)
|
||||
else:
|
||||
elif (sign == 'ecc256'):
|
||||
r, s = ecc.sign_raw(digest)
|
||||
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
|
||||
#print ("len sig: %d\n" % len(signature))
|
||||
#print([hex(j) for j in signature])
|
||||
print ("Done.")
|
||||
|
||||
# Create output image. Add padded header in front
|
||||
outfile = open(output_image_file, 'wb')
|
||||
outfile.write(header)
|
||||
sz = len(header)
|
||||
while sz < 256:
|
||||
while sz < WOLFBOOT_HEADER_SIZE:
|
||||
outfile.write(struct.pack('B',0xFF))
|
||||
sz += 1
|
||||
infile = open(image_file, 'rb')
|
||||
|
|
Loading…
Reference in New Issue