diff --git a/IDE/XilinxSDK/.cproject b/IDE/XilinxSDK/.cproject index e047d41f4..170006ff4 100644 --- a/IDE/XilinxSDK/.cproject +++ b/IDE/XilinxSDK/.cproject @@ -37,6 +37,7 @@ + @@ -51,6 +52,7 @@ + @@ -76,6 +78,7 @@ + @@ -90,6 +93,7 @@ + @@ -169,6 +173,7 @@ + @@ -183,6 +188,7 @@ + @@ -208,6 +214,7 @@ + @@ -222,6 +229,7 @@ + diff --git a/IDE/XilinxSDK/README.md b/IDE/XilinxSDK/README.md index 8cc880c64..14e26c270 100644 --- a/IDE/XilinxSDK/README.md +++ b/IDE/XilinxSDK/README.md @@ -23,7 +23,14 @@ You may need to adjust/add the following project settings under Properties -> C/ ## wolfBoot Configuration -A build settings template for Zynq UltraScale+ can be found here `./config/examples/zynqmp.config`. This file can be copied to wolfBoot root as `.config` for building from the command line. These template settings are also in this `.cproject` as preprocessor macros. These settings are loaded into the `target.h.in` template by the wolfBoot `make`. If not using the built-in make then the following defines will need to be manually created in `target.h`: +A build settings template for Zynq UltraScale+ can be found here `./config/examples/zynqmp.config`. This file can be copied to wolfBoot root as `.config` for building from the command line. + +```sh +$ cp ./config/examples/zynqmp.config .config +$ make keytools +``` + +These template settings are also in this `.cproject` as preprocessor macros. These settings are loaded into the `target.h.in` template by the wolfBoot `make`. If not using the built-in make then the following defines will need to be manually created in `target.h`: ``` #define WOLFBOOT_SECTOR_SIZE 0x20000 @@ -40,10 +47,25 @@ A build settings template for Zynq UltraScale+ can be found here `./config/examp Note: If not using Position Independent Code (PIC) the linker script `ldscript.ld` must have the start address offset to match the `WOLFBOOT_LOAD_ADDRESS`. +## Generate signing key + +The keygen tool creates an RSA 4096-bit private key (`wolfboot_signing_private_key.der`) and exports the public key to `src/keystore.c` for wolfBoot to use at compile-time as the default root-of-trust. + +```sh +$ ./tools/keytools/keygen --rsa4096 -g wolfboot_signing_private_key.der +Keytype: RSA4096 +Generating key (type: RSA4096) +RSA public key len: 550 bytes +Associated key file: wolfboot_signing_private_key.der +Partition ids mask: ffffffff +Key type : RSA4096 +Public key slot: 0 +Done. +``` + ## Signing Example ```sh -$ make keytools $ ./tools/keytools/sign --rsa4096 --sha3 ../hello_world/Debug/hello_world.elf ./wolfboot_signing_private_key.der 1 wolfBoot KeyTools (Compiled C version) wolfBoot version 2020000 @@ -115,11 +137,24 @@ Read FlashID Upper: Ret 0, 20 BB 20 Versions: Boot 1, Update 0 Trying Boot partition at 800000 Boot partition: 800000 (size 226024, version 0x1) +info: LMS wolfBoot_verify_signature +info: using LMS parameters: L2-H5-W8 +info: wc_LmsKey_Verify returned OK +Successfully selected image in part: 0 Firmware Valid -Loading 226024 bytes to RAM at 10000000 +Loading flash image from 8014A8 to RAM at 10000000 (226024 bytes) +Loading elf at 10000000 +Found valid elf64 (little endian) +Program Headers 2 (size 56) +Load 57536 bytes (offset 10000) to 0 (p 0) +Clear 20600 bytes at 0 (p 0) +Entry point 0 DTB boot partition: 7B0000 Failed parsing DTB to load -Booting at 10000000 +Booting at 0 +Hello World + +Successfully ran Hello World application ``` @@ -156,11 +191,109 @@ Note: To generate a report of a boot.bin use the `bootgen_utility`: ## Post Quantum -XMSS +### PQ XMSS + +1) Add these build symbols to the Xilinx project: +Note: Make sure and remove the existing `WOLFBOOT_SIGN_*`, `WOLFBOOT_HASH_*` and `IMAGE_HEADER_SIZE` + +``` +WOLFBOOT_SIGN_XMSS +WOLFBOOT_HASH_SHA256 +WOLFSSL_HAVE_XMSS +WOLFSSL_WC_XMSS +WOLFSSL_WC_XMSS_SMALL +WOLFBOOT_XMSS_PARAMS="'XMSS-SHA2_10_256'" +WOLFSSL_XMSS_VERIFY_ONLY +WOLFSSL_XMSS_MAX_HEIGHT=32 +WOLFBOOT_SHA_BLOCK_SIZE=4096 +IMAGE_SIGNATURE_SIZE=2500 +IMAGE_HEADER_SIZE=4096 +``` + +2) Create and sign image: ```sh -./tools/keytools/keygen --xmss -g wolfboot_signing_private_key.der -./tools/keytools/sign --xmss test-app/image.bin wolfboot_signing_private_key.der 1 +$ ./tools/keytools/keygen --xmss -g wolfboot_signing_private_key.der +Keytype: XMSS +Generating key (type: XMSS) +info: using XMSS parameters: XMSS-SHA2_10_256 +Associated key file: wolfboot_signing_private_key.der +Partition ids mask: ffffffff +Key type : XMSS +Public key slot: 0 +Done. + +$ ./tools/keytools/sign --xmss ../hello_world/Debug/hello_world.elf wolfboot_signing_private_key.der 1 +wolfBoot KeyTools (Compiled C version) +wolfBoot version 2020000 +Update type: Firmware +Input image: ../hello_world/Debug/hello_world.elf +Selected cipher: XMSS +Selected hash : SHA256 +Public key: wolfboot_signing_private_key.der +Output image: ../hello_world/Debug/hello_world_v1_signed.bin +Target partition id : 1 +info: using XMSS parameters: XMSS-SHA2_10_256 +info: XMSS signature size: 2500 +info: xmss sk len: 1343 +info: xmss pk len: 68 +Found XMSS key +image header size calculated at runtime (5000 bytes) +Calculating SHA256 digest... +Signing the digest... +Output image(s) successfully created. +``` + +### PQ LMS + +1) Add these build symbols to the Xilinx project: +Note: Make sure and remove the existing `WOLFBOOT_SIGN_*`, `WOLFBOOT_HASH_*` and `IMAGE_HEADER_SIZE` + +``` +WOLFBOOT_SIGN_LMS +WOLFBOOT_HASH_SHA256 +WOLFSSL_HAVE_LMS +WOLFSSL_WC_LMS +WOLFSSL_WC_LMS_SMALL +WOLFSSL_LMS_VERIFY_ONLY +WOLFSSL_LMS_MAX_LEVELS=2 +WOLFSSL_LMS_MAX_HEIGHT=5 +LMS_LEVELS=2 +LMS_HEIGHT=5 +LMS_WINTERNITZ=8 +IMAGE_SIGNATURE_SIZE=2644 +IMAGE_HEADER_SIZE=5288 +``` +2) Create and sign image: + +```sh +$ ./tools/keytools/keygen --lms -g wolfboot_signing_private_key.der +Keytype: LMS +Generating key (type: LMS) +info: using LMS parameters: L2-H5-W8 +Associated key file: wolfboot_signing_private_key.der +Partition ids mask: ffffffff +Key type : LMS +Public key slot: 0 +Done. + +$ ./tools/keytools/sign --lms ../hello_world/Debug/hello_world.elf wolfboot_signing_private_key.der 1 +wolfBoot KeyTools (Compiled C version) +wolfBoot version 2020000 +Update type: Firmware +Input image: ../hello_world/Debug/hello_world.elf +Selected cipher: LMS +Selected hash : SHA256 +Public key: wolfboot_signing_private_key.der +Output image: ../hello_world/Debug/hello_world_v1_signed.bin +Target partition id : 1 +info: using LMS parameters: L2-H5-W8 +info: LMS signature size: 2644 +Found LMS key +image header size calculated at runtime (5288 bytes) +Calculating SHA256 digest... +Signing the digest... +Output image(s) successfully created. ``` diff --git a/arch.mk b/arch.mk index 1a791725b..92dbe8319 100644 --- a/arch.mk +++ b/arch.mk @@ -953,7 +953,7 @@ ifeq ($(TARGET),x86_64_efi) CFLAGS += -I/usr/include/efi -I/usr/include/efi/x86_64 \ -DTARGET_X86_64_EFI -DWOLFBOOT_DUALBOOT # avoid using of fixed LOAD_ADDRESS, uefi target uses dynamic location - CFLAGS += -DNO_WOLFBOOT_LOAD_ADDRESS + CFLAGS += -DWOLFBOOT_NO_LOAD_ADDRESS LDFLAGS = -shared -Bsymbolic -L/usr/lib -T$(GNU_EFI_LSCRIPT) LD_START_GROUP = $(GNU_EFI_CRT0) LD_END_GROUP = -lgnuefi -lefi diff --git a/config/examples/zynqmp.config b/config/examples/zynqmp.config index 95595b4f0..a67ab205d 100644 --- a/config/examples/zynqmp.config +++ b/config/examples/zynqmp.config @@ -17,7 +17,17 @@ IMAGE_HEADER_SIZE?=1024 #IMAGE_SIGNATURE_SIZE=2500 #IMAGE_HEADER_SIZE?=5000 -DEBUG?=1 +# LMS/HSS is a post-quantum, stateful, hash-based signature scheme. +# Use the helper script `tools/lms/lms_siglen` +#SIGN?=LMS +#HASH?=SHA256 +#LMS_LEVELS=2 +#LMS_HEIGHT=5 +#LMS_WINTERNITZ=8 +#IMAGE_SIGNATURE_SIZE=2644 +#IMAGE_HEADER_SIZE?=5288 + +DEBUG?=0 DEBUG_UART=1 #DEBUG_ZYNQ=1 @@ -37,6 +47,7 @@ EXT_FLASH?=1 SPI_FLASH?=0 NO_XIP=1 USE_GCC=1 +ELF?=1 # Flash Sector Size WOLFBOOT_SECTOR_SIZE=0x20000 diff --git a/hal/zynq.c b/hal/zynq.c index 5977a363a..fd1b31ac9 100644 --- a/hal/zynq.c +++ b/hal/zynq.c @@ -1301,7 +1301,7 @@ int RAMFUNCTION ext_flash_read(uintptr_t address, uint8_t *data, int len) wolfBoot_printf("Flash Read: Ret %d\r\n", ret); #endif - return ret; + return (ret == 0) ? len : ret; } /* Issues a sector erase based on flash address */ diff --git a/include/target.h.in b/include/target.h.in index 14c5216fc..2ba08c95a 100644 --- a/include/target.h.in +++ b/include/target.h.in @@ -92,7 +92,7 @@ #endif /* WOLFBOOT_FIXED_PARTITIONS */ -#if !defined(NO_WOLFBOOT_LOAD_ADDRESS) +#if !defined(WOLFBOOT_NO_LOAD_ADDRESS) /* Load address in RAM for staged OS (update_ram only) */ #define WOLFBOOT_LOAD_ADDRESS @WOLFBOOT_LOAD_ADDRESS@ #endif diff --git a/include/user_settings.h b/include/user_settings.h index 6c37612f6..d4ca0c922 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -366,7 +366,8 @@ extern int tolower(int c); # define WC_NO_HASHDRBG # define NO_DEV_RANDOM # define NO_ECC_KEY_EXPORT -# ifdef NO_RSA +# if defined(NO_RSA) && !defined(WOLFSSL_HAVE_XMSS) && \ + !defined(WOLFSSL_HAVE_LMS) # define NO_ASN # endif #endif diff --git a/options.mk b/options.mk index 20174bf0c..f770791e6 100644 --- a/options.mk +++ b/options.mk @@ -378,7 +378,7 @@ ifeq ($(SIGN),LMS) ifeq ($(WOLFBOOT_SMALL_STACK),1) $(error WOLFBOOT_SMALL_STACK with LMS not supported) else - STACK_USAGE=1024 + STACK_USAGE=1296 endif endif @@ -447,7 +447,7 @@ ifeq ($(SIGN),XMSS) ifeq ($(WOLFBOOT_SMALL_STACK),1) $(error WOLFBOOT_SMALL_STACK with XMSS not supported) else - STACK_USAGE=2688 + STACK_USAGE=2720 endif endif diff --git a/src/image.c b/src/image.c index bad8f926f..ded512658 100644 --- a/src/image.c +++ b/src/image.c @@ -351,7 +351,6 @@ static void wolfBoot_verify_signature(uint8_t key_slot, { int ret = 0; LmsKey lms; - word32 pub_len = 0; uint8_t * pubkey = NULL; wolfBoot_printf("info: LMS wolfBoot_verify_signature\n"); @@ -419,7 +418,6 @@ static void wolfBoot_verify_signature(uint8_t key_slot, { int ret = 0; XmssKey xmss; - word32 pub_len = 0; uint8_t * pubkey = NULL; wolfBoot_printf("info: XMSS wolfBoot_verify_signature\n"); diff --git a/src/qspi_flash.c b/src/qspi_flash.c index 6959d969c..1bea1fc49 100644 --- a/src/qspi_flash.c +++ b/src/qspi_flash.c @@ -416,7 +416,8 @@ int spi_flash_read(uint32_t address, void *data, int len) ret, address, len, FLASH_READ_CMD); #endif - return ret; + /* external flash read expects length returned */ + return (ret == 0) ? len : ret; } int spi_flash_write(uint32_t address, const void *data, int len) diff --git a/src/update_ram.c b/src/update_ram.c index 7d1276a75..edd8591fc 100644 --- a/src/update_ram.c +++ b/src/update_ram.c @@ -48,6 +48,8 @@ extern uint32_t dts_load_addr; #endif #ifdef WOLFBOOT_USE_RAMBOOT + +#if !(defined(EXT_FLASH) && defined(NO_XIP)) /* requires/assumes inputs and size to be 4-byte aligned */ static void memcpy32(void *dst, const void *src, size_t n) { @@ -58,6 +60,7 @@ static void memcpy32(void *dst, const void *src, size_t n) d[i] = s[i]; } } +#endif /* Function to load image from flash to ram */ int wolfBoot_ramboot(struct wolfBoot_image *img, uint8_t *src, uint8_t *dst) @@ -107,7 +110,7 @@ int wolfBoot_ramboot(struct wolfBoot_image *img, uint8_t *src, uint8_t *dst) return 0; /* success */ } -#endif +#endif /* WOLFBOOT_USE_RAMBOOT */ void RAMFUNCTION wolfBoot_start(void) { @@ -261,11 +264,23 @@ void RAMFUNCTION wolfBoot_start(void) #endif #ifndef WOLFBOOT_USE_RAMBOOT - /* if needed copy image to RAM */ - wolfBoot_printf("Loading %d bytes to RAM at %p\n", os_image.fw_size, - load_address); + /* copy image to RAM */ + #if defined(EXT_FLASH) && defined(NO_XIP) + wolfBoot_printf("Loading flash image from %p to RAM at %p (%d bytes)\n", + os_image.fw_base, load_address, os_image.fw_size); + ret = ext_flash_read((uintptr_t)os_image.fw_base, (uint8_t*)load_address, + os_image.fw_size); + if (ret < 0){ + wolfBoot_printf("Error loading image at %p (ret %d)\n", + os_image.fw_base, ret); + return; + } + #else + wolfBoot_printf("Copying image from %p to RAM at %p (%d bytes)\n", + os_image.fw_base, load_address, os_image.fw_size); memcpy((void*)load_address, os_image.fw_base, os_image.fw_size); -#endif + #endif +#endif /* !WOLFBOOT_USE_RAMBOOT */ #ifdef WOLFBOOT_ELF /* Load elf */ diff --git a/src/xmalloc.c b/src/xmalloc.c index d08aaa1d8..f4aac6b24 100644 --- a/src/xmalloc.c +++ b/src/xmalloc.c @@ -371,7 +371,8 @@ static uint8_t asncheck_buf[ASNCHECK_BUF_SIZE]; }; #endif -#elif defined WOLFBOOT_NO_SIGN +#elif defined(WOLFBOOT_NO_SIGN) || defined(WOLFBOOT_SIGN_XMSS) || \ + defined(WOLFBOOT_SIGN_LMS) #define MP_SCHEME "NONE" static uint32_t sha_block[HASH_BLOCK_SIZE]; @@ -383,7 +384,7 @@ static struct xmalloc_slot xmalloc_pool[] = { }; #else -# error "No cipher selected." +# error "No signing scheme selected." #endif #ifdef WOLFBOOT_DEBUG_MALLOC diff --git a/stage1/loader_stage1.c b/stage1/loader_stage1.c index e5186aff2..4ecc6a2d8 100644 --- a/stage1/loader_stage1.c +++ b/stage1/loader_stage1.c @@ -22,6 +22,8 @@ /* A stage 1 loader to copy wolfBoot from flash to RAM location */ +#ifdef BUILD_LOADER_STAGE1 + #include "loader.h" #include "image.h" #include "hal.h" @@ -41,8 +43,6 @@ #define WOLFBOOT_STAGE1_SIZE (4*1024) #endif -#ifdef BUILD_LOADER_STAGE1 - #ifdef WOLFBOOT_ARCH_PPC #include "hal/nxp_ppc.h" #endif diff --git a/tools/keytools/Makefile b/tools/keytools/Makefile index bbb1f5b54..f1aa73676 100644 --- a/tools/keytools/Makefile +++ b/tools/keytools/Makefile @@ -67,9 +67,12 @@ SANITIZE_FLAGS = -fsanitize=address OPTIMIZE = -O2 # Options -#CFLAGS+=$(DEBUG_FLAGS) -#CFLAGS+=$(SANITIZE_FLAGS) -CFLAGS+=$(OPTIMIZE) +ifeq ($(DEBUG),1) + CFLAGS+=$(DEBUG_FLAGS) +else + #CFLAGS+=$(SANITIZE_FLAGS) + CFLAGS+=$(OPTIMIZE) +endif ifeq ($(IMAGE_HEADER_SIZE),) IMAGE_HEADER_SIZE=256 diff --git a/tools/keytools/keygen.c b/tools/keytools/keygen.c index 9d2c67f71..2e4d279fe 100644 --- a/tools/keytools/keygen.c +++ b/tools/keytools/keygen.c @@ -662,7 +662,7 @@ static void keygen_lms(const char *priv_fname, uint32_t id_mask) } /* Append the public key to the private keyfile. */ - fpriv = fopen(priv_fname, "r+"); + fpriv = fopen(priv_fname, "rb+"); if (!fpriv) { fprintf(stderr, "error: fopen(%s, \"r+\") returned %d\n", priv_fname, ret); @@ -752,7 +752,7 @@ static void keygen_xmss(const char *priv_fname, uint32_t id_mask) } /* Append the public key to the private keyfile. */ - fpriv = fopen(priv_fname, "r+"); + fpriv = fopen(priv_fname, "rb+"); if (!fpriv) { fprintf(stderr, "error: fopen(%s, \"r+\") returned %d\n", priv_fname, ret); @@ -1072,7 +1072,7 @@ int main(int argc, char** argv) } fpub = NULL; } - fpub = fopen(pubkeyfile, "w"); + fpub = fopen(pubkeyfile, "wb"); if (fpub == NULL) { fprintf(stderr, "Unable to open file '%s' for writing: %s", pubkeyfile, strerror(errno)); exit(4); diff --git a/tools/keytools/sign.c b/tools/keytools/sign.c index e487f4fb9..58459cb3f 100644 --- a/tools/keytools/sign.c +++ b/tools/keytools/sign.c @@ -709,11 +709,11 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, } /* The XMSS file callbacks will handle writing and reading the - * private key. We only need to set the public key here. - * - * If both priv/pub are present: - * - The first ?? bytes is the private key. - * - The next 68 bytes is the public key. */ + * private key. We only need to set the public key here. + * + * If both priv/pub are present: + * - The first ?? bytes is the private key. + * - The next 68 bytes is the public key. */ ret = wc_XmssKey_GetPrivLen(&key.xmss, &priv_sz); if (ret != 0 || priv_sz <= 0) { printf("error: wc_XmssKey_GetPrivLen returned %d\n", ret);