Fixes for building wolfBoot with XMSS/LMS.

pull/491/head
David Garske 2024-08-13 16:07:38 -07:00 committed by Daniele Lacamera
parent be169145e2
commit 9e17315d49
16 changed files with 208 additions and 37 deletions

View File

@ -37,6 +37,7 @@
<listOptionValue builtIn="false" value="TARGET_zynq"/>
<listOptionValue builtIn="false" value="ARCH_AARCH64"/>
<listOptionValue builtIn="false" value="MMU"/>
<listOptionValue builtIn="false" value="NO_XIP"/>
<listOptionValue builtIn="false" value="PART_UPDATE_EXT=1"/>
<listOptionValue builtIn="false" value="PART_SWAP_EXT=1"/>
<listOptionValue builtIn="false" value="PART_BOOT_EXT=1"/>
@ -51,6 +52,7 @@
<listOptionValue builtIn="false" value="WOLFTPM_USER_SETTINGS"/>
<listOptionValue builtIn="false" value="WOLFPKCS11_USER_SETTINGS"/>
<listOptionValue builtIn="false" value="WOLFBOOT_DUALBOOT"/>
<listOptionValue builtIn="false" value="WOLFBOOT_ELF"/>
</option>
<option id="xilinx.gnu.compiler.dircategory.includes.398847842" name="Include Paths" superClass="xilinx.gnu.compiler.dircategory.includes" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>
@ -76,6 +78,7 @@
<listOptionValue builtIn="false" value="TARGET_zynq"/>
<listOptionValue builtIn="false" value="ARCH_AARCH64"/>
<listOptionValue builtIn="false" value="MMU"/>
<listOptionValue builtIn="false" value="NO_XIP"/>
<listOptionValue builtIn="false" value="PART_UPDATE_EXT=1"/>
<listOptionValue builtIn="false" value="PART_SWAP_EXT=1"/>
<listOptionValue builtIn="false" value="PART_BOOT_EXT=1"/>
@ -90,6 +93,7 @@
<listOptionValue builtIn="false" value="WOLFTPM_USER_SETTINGS"/>
<listOptionValue builtIn="false" value="WOLFPKCS11_USER_SETTINGS"/>
<listOptionValue builtIn="false" value="WOLFBOOT_DUALBOOT"/>
<listOptionValue builtIn="false" value="WOLFBOOT_ELF"/>
</option>
<option id="xilinx.gnu.compiler.dircategory.includes.1725565215" name="Include Paths" superClass="xilinx.gnu.compiler.dircategory.includes" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>
@ -169,6 +173,7 @@
<listOptionValue builtIn="false" value="TARGET_zynq"/>
<listOptionValue builtIn="false" value="ARCH_AARCH64"/>
<listOptionValue builtIn="false" value="MMU"/>
<listOptionValue builtIn="false" value="NO_XIP"/>
<listOptionValue builtIn="false" value="PART_UPDATE_EXT=1"/>
<listOptionValue builtIn="false" value="PART_SWAP_EXT=1"/>
<listOptionValue builtIn="false" value="PART_BOOT_EXT=1"/>
@ -183,6 +188,7 @@
<listOptionValue builtIn="false" value="WOLFTPM_USER_SETTINGS"/>
<listOptionValue builtIn="false" value="WOLFPKCS11_USER_SETTINGS"/>
<listOptionValue builtIn="false" value="WOLFBOOT_DUALBOOT"/>
<listOptionValue builtIn="false" value="WOLFBOOT_ELF"/>
</option>
<option id="xilinx.gnu.compiler.dircategory.includes.1446899274" name="Include Paths" superClass="xilinx.gnu.compiler.dircategory.includes" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>
@ -208,6 +214,7 @@
<listOptionValue builtIn="false" value="TARGET_zynq"/>
<listOptionValue builtIn="false" value="ARCH_AARCH64"/>
<listOptionValue builtIn="false" value="MMU"/>
<listOptionValue builtIn="false" value="NO_XIP"/>
<listOptionValue builtIn="false" value="PART_UPDATE_EXT=1"/>
<listOptionValue builtIn="false" value="PART_SWAP_EXT=1"/>
<listOptionValue builtIn="false" value="PART_BOOT_EXT=1"/>
@ -222,6 +229,7 @@
<listOptionValue builtIn="false" value="WOLFTPM_USER_SETTINGS"/>
<listOptionValue builtIn="false" value="WOLFPKCS11_USER_SETTINGS"/>
<listOptionValue builtIn="false" value="WOLFBOOT_DUALBOOT"/>
<listOptionValue builtIn="false" value="WOLFBOOT_ELF"/>
</option>
<option id="xilinx.gnu.compiler.dircategory.includes.438324592" name="Include Paths" superClass="xilinx.gnu.compiler.dircategory.includes" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>

View File

@ -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.
```

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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)

View File

@ -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 @@ backup_on_failure:
#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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);