diff --git a/.github/workflows/test-sunnyday-simulator.yml b/.github/workflows/test-sunnyday-simulator.yml index 35c8baac3..133999ae7 100644 --- a/.github/workflows/test-sunnyday-simulator.yml +++ b/.github/workflows/test-sunnyday-simulator.yml @@ -558,3 +558,20 @@ jobs: run: | tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-ml-dsa.config + # 64 Bit simulator, Hybrid auth ML_DSA + ECDSA + # + - name: make clean + run: | + make distclean + + - name: Select config (64 bit simulator) Hybrid ML_DSA + ECC + run: | + cp config/examples/sim-ml-dsa-ecc-hybrid.config .config + + - name: Build wolfboot.elf + run: | + make clean && make + + - name: Run sunny day hybrid boot test + run: | + ./wolfboot.elf get_version diff --git a/.github/workflows/test-tpm.yml b/.github/workflows/test-tpm.yml index 0b1903648..2e0303753 100644 --- a/.github/workflows/test-tpm.yml +++ b/.github/workflows/test-tpm.yml @@ -113,7 +113,7 @@ jobs: with: arch: host config-file: ./config/examples/sim-tpm-seal.config - make-args: SIGN=ECC256 HASH=SHA256 POLICY_FILE=policy.bin + make-args: SIGN=ECC256 HASH=SHA256 POLICY_FILE=policy.bin IMAGE_HEADER_SIZE=512 keyauthstr: TestAuth sealauthstr: SealAuth @@ -143,7 +143,7 @@ jobs: with: arch: host config-file: ./config/examples/sim-tpm-seal.config - make-args: SIGN=ECC256 HASH=SHA256 POLICY_FILE=policy.bin + make-args: SIGN=ECC256 HASH=SHA256 POLICY_FILE=policy.bin IMAGE_HEADER_SIZE=512 keyauthstr: TestAuth sim_tpm_seal_noauth_ecc384: diff --git a/Makefile b/Makefile index 1addb7017..cb12542c7 100644 --- a/Makefile +++ b/Makefile @@ -141,9 +141,13 @@ ifeq ($(FLASH_OTP_KEYSTORE),1) MAIN_TARGET+=tools/keytools/otp/otp-keystore-primer.bin endif +ifneq ($(SIGN_SECONDARY),) + SECONDARY_PRIVATE_KEY=wolfboot_signing_second_private_key.der +endif + ASFLAGS:=$(CFLAGS) -all: $(MAIN_TARGET) +all: $(SECONDARY_PRIVATE_KEY) $(MAIN_TARGET) stage1: stage1/loader_stage1.bin stage1/loader_stage1.bin: wolfboot.elf @@ -203,6 +207,15 @@ $(PRIVATE_KEY): $(Q)(test $(SIGN) = NONE) && (echo "// SIGN=NONE" > src/keystore.c) || true $(Q)(test "$(FLASH_OTP_KEYSTORE)" = "1") && (make -C tools/keytools/otp) || true +$(SECONDARY_PRIVATE_KEY): $(PRIVATE_KEY) keystore.der + $(Q)$(MAKE) keytools_check + $(Q)rm -f src/keystore.c + $(Q)dd if=keystore.der of=pubkey_1.der bs=1 skip=16 + $(Q)(test $(SIGN_SECONDARY) = NONE) || ("$(KEYGEN_TOOL)" \ + $(KEYGEN_OPTIONS) -i pubkey_1.der $(SECONDARY_KEYGEN_OPTIONS) \ + -g $(SECONDARY_PRIVATE_KEY)) || true + $(Q)(test "$(FLASH_OTP_KEYSTORE)" = "1") && (make -C tools/keytools/otp) || true + keytools: include/target.h @echo "Building key tools" @$(MAKE) -C tools/keytools -s clean @@ -220,7 +233,12 @@ swtpmtools: test-app/image_v1_signed.bin: $(BOOT_IMG) @echo "\t[SIGN] $(BOOT_IMG)" - $(Q)(test $(SIGN) = NONE) || "$(SIGN_TOOL)" $(SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) 1 + @echo "\tSECONDARY_SIGN_OPTIONS=$(SECONDARY_SIGN_OPTIONS)" + @echo "\tSECONDARY_PRIVATE_KEY=$(SECONDARY_PRIVATE_KEY)" + + $(Q)(test $(SIGN) = NONE) || "$(SIGN_TOOL)" $(SIGN_OPTIONS) \ + $(SECONDARY_SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) \ + $(SECONDARY_PRIVATE_KEY) 1 || true $(Q)(test $(SIGN) = NONE) && "$(SIGN_TOOL)" $(SIGN_OPTIONS) $(BOOT_IMG) 1 || true test-app/image.elf: wolfboot.elf @@ -312,7 +330,7 @@ keys: $(PRIVATE_KEY) clean: $(Q)rm -f src/*.o hal/*.o hal/spi/*.o test-app/*.o src/x86/*.o - $(Q)rm -f lib/wolfssl/wolfcrypt/src/*.o lib/wolfTPM/src/*.o lib/wolfTPM/hal/*.o + $(Q)rm -f lib/wolfssl/wolfcrypt/src/*.o lib/wolfTPM/src/*.o lib/wolfTPM/hal/*.o lib/wolfTPM/examples/pcr/*.o $(Q)rm -f lib/wolfssl/wolfcrypt/src/port/Renesas/*.o $(Q)rm -f wolfboot.bin wolfboot.elf wolfboot.map test-update.rom wolfboot.hex $(Q)rm -f $(MACHINE_OBJ) $(MAIN_TARGET) $(LSCRIPT) @@ -408,6 +426,8 @@ tools/keytools/otp/otp-keystore-primer.bin: FORCE make -C tools/keytools/otp clean make -C tools/keytools/otp +secondary: $(SECONDARY_PRIVATE_KEY) + %.o:%.c @echo "\t[CC-$(ARCH)] $@" $(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ $^ diff --git a/arch.mk b/arch.mk index fad907b40..af5f279d8 100644 --- a/arch.mk +++ b/arch.mk @@ -25,8 +25,13 @@ SPI_TARGET=$(TARGET) # Default UART driver name UART_TARGET=$(TARGET) -# Include SHA256 module because it's implicitly needed by RSA -WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/sha256.o +# Include some modules by default +WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/sha256.o \ + ./lib/wolfssl/wolfcrypt/src/hash.o \ + ./lib/wolfssl/wolfcrypt/src/memory.o \ + ./lib/wolfssl/wolfcrypt/src/wc_port.o \ + ./lib/wolfssl/wolfcrypt/src/wolfmath.o + ifeq ($(ARCH),x86_64) CFLAGS+=-DARCH_x86_64 @@ -239,7 +244,6 @@ else CORTEXM_ARM_EXTRA_OBJS= CORTEXM_ARM_EXTRA_CFLAGS= SECURE_OBJS+=./src/wc_callable.o - SECURE_OBJS+=./lib/wolfssl/wolfcrypt/src/random.o CFLAGS+=-DWOLFCRYPT_SECURE_MODE SECURE_LDFLAGS+=-Wl,--cmse-implib -Wl,--out-implib=./src/wc_secure_calls.o endif @@ -1025,6 +1029,7 @@ ifeq ($(TARGET),sim) LD_END_GROUP= BOOT_IMG=test-app/image.elf CFLAGS+=-DARCH_SIM + CFLAGS+=-DWOLFBOOT_USE_STDLIBC ifeq ($(FORCE_32BIT),1) CFLAGS+=-m32 LDFLAGS+=-m32 diff --git a/config/examples/sim-ml-dsa-ecc-hybrid.config b/config/examples/sim-ml-dsa-ecc-hybrid.config new file mode 100644 index 000000000..dd6f64b69 --- /dev/null +++ b/config/examples/sim-ml-dsa-ecc-hybrid.config @@ -0,0 +1,26 @@ +ARCH=sim +TARGET=sim +SIGN?=ML_DSA +ML_DSA_LEVEL=3 +IMAGE_SIGNATURE_SIZE=3309 +IMAGE_HEADER_SIZE?=8192 +HASH?=SHA256 +WOLFBOOT_SMALL_STACK?=0 +SPI_FLASH=0 +DEBUG=0 +WOLFBOOT_UNIVERSAL_KEYSTORE=1 +SIGN_SECONDARY=ECC384 + +# sizes should be multiple of system page size +WOLFBOOT_PARTITION_SIZE=0x40000 +WOLFBOOT_SECTOR_SIZE=0x1000 +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80000 +# if on external flash, it should be multiple of system page size +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x100000 +WOLFBOOT_PARTITION_SWAP_ADDRESS=0x180000 + +# required for keytools +WOLFBOOT_FIXED_PARTITIONS=1 + +# For debugging XMALLOC/XFREE +#CFLAGS_EXTRA+=-DWOLFBOOT_DEBUG_MALLOC diff --git a/docs/PQ.md b/docs/PQ.md index 8255e8611..2ceeb0b90 100644 --- a/docs/PQ.md +++ b/docs/PQ.md @@ -178,6 +178,109 @@ parameter set: XMSSMT-SHA2_20/2_256 signature length: 4963 ``` +## Hybrid mode (classic + PQ) + +wolfBoot supports a hybrid mode where both classic and PQ signatures are verified, +sequentially. This allows for a gradual transition from classic to PQ signatures, +and protects the secure boot mechanism from potential vulnerabilities in either of +the two ciphers in use. + +The hybrid mode is enabled by setting a `SECONDARY_SIGN` option in the config file, +which specifies the secondary signature algorithm to be used. The secondary signature +option requires the option `WOLFBOOT_UNIVERSAL_KEYSTORE=1`, to ensure that the +keystore can handle both classic and PQ keys. + +The secondary signature option can be set to any of the supported PQ signature options. + +The example configuration provided in `config/examples/sim-ml-dsa-ecc-hybrid.config` +demonstrates the use of hybrid mode with both ML-DSA-65 and ECC-384. + +### Hybrid signature + +The `sign` tool supports hybrid signatures. It is sufficient to specify two +ciphers argument from command line. When you do that, the tool expects two private +key files path passed as arguments, instead of one. + +The two public keys must be added to the same keystore. For this reason, the two +keypairs must be generated either at the same time, or in two subsequent steps. + +### Generating keypairs for hybrid signatures + +#### Generate both keys at the same time: + +``` +./tools/keytools/keygen --ml_dsa -g wolfboot_signing_private_key.der --ecc384 -g wolfboot_signing_second_private_key.der +``` + +both keys are automatically added to the same keystore. + + +#### Generate the two keys in separate steps + +If you want to generate the keys in two steps, you will have to import the first +key in the new keystore. The first public key is stored in `keystore.der` during +the keypair generation: +``` +./tools/keytools/keygen --ml_dsa -g wolfboot_signing_private_key.der +``` + +The first 16 bytes contain the keystore header, and must be skipped: + +``` +dd if=keystore.der of=ml_dsa-pubkey.der bs=1 skip=16 +``` + +The new keypair can be generated (`-g`) while importing (`-i`)the old public key: + +``` +./tools/keytools/keygen --ml_dsa -i ml_dsa-pubkey.der -g --ecc384 wolfboot_signing_second_private_key.der +``` + +The keystore generated is now ready to be used by wolfBoot for hybrid signature verification. + +### Hybrid signature of the firmware + +In both examples above, the two private keys are now available in separate .der files. +The `sign` tool can now be used to sign the firmware with both keys: + +``` +./tools/sign/sign --ml_dsa --ecc384 --sha256 test-app/image.elf wolfboot_signing_private_key.der wolfboot_signing_second_private_key.der 1 +``` + +The command should confirm that both keys are loaded, and that the image is signed and includes the hybrid signature: +``` +wolfBoot KeyTools (Compiled C version) +wolfBoot version 2020000 +Parsing arguments in hybrid mode +Secondary private key: wolfboot_signing_second_private_key.der +Secondary cipher: ECC384 +Version: 1 +Update type: Firmware +Input image: test-app/image.elf +Selected cipher: ML-DSA +Selected hash : SHA256 +Private key: wolfboot_signing_private_key.der +Secondary cipher: ECC384 +Secondary private key: wolfboot_signing_second_private_key.der +Output image: test-app/image_v1_signed.bin +Target partition id : 1 +info: using ML-DSA parameters: 3 +info: ML-DSA signature size: 3309 +Key buffer size: 5984 +info: ml-dsa priv len: 4032 +info: ml-dsa pub len: 1952 +Found ml-dsa key +image header size overridden by config value (8192 bytes) +Loading secondary key +Key buffer size: 144 +Secondary ECC key, size: 96 +image header size overridden by config value (8192 bytes) +Creating hybrid signature +[...] +``` + +The resulting image `image_v1_signed.bin` contains both signatures, and can be verified using a wolfBoot with hybrid signature support. + ## Building the external PQ Integrations ### ext_LMS Support diff --git a/hal/sim.c b/hal/sim.c index b973bad04..215916c12 100644 --- a/hal/sim.c +++ b/hal/sim.c @@ -40,6 +40,7 @@ #include "wolfboot/wolfboot.h" #include "target.h" +#include "printf.h" /* Global pointer to the internal and external flash base */ uint8_t *sim_ram_base; @@ -72,7 +73,7 @@ static int mmap_file(const char *path, uint8_t *address, uint8_t** ret_address) fd = open(path, O_RDWR); if (fd == -1) { - fprintf(stderr, "can't open %s\n", path); + wolfBoot_printf( "can't open %s\n", path); return -1; } @@ -81,7 +82,7 @@ static int mmap_file(const char *path, uint8_t *address, uint8_t** ret_address) if (mmaped_addr == MAP_FAILED) return -1; - fprintf(stderr, "Simulator assigned %s to base %p\n", path, mmaped_addr); + wolfBoot_printf( "Simulator assigned %s to base %p\n", path, mmaped_addr); *ret_address = mmaped_addr; @@ -119,8 +120,8 @@ int hal_flash_write(uintptr_t address, const uint8_t *data, int len) uint8_t *addr = (uint8_t *)address; if (addr[i] != FLASH_BYTE_ERASED) { /* no writing to non-erased page in NVM_FLASH_WRITEONCE */ - printf("NVM_FLASH_WRITEONCE non-erased write detected at address %p!\n", addr); - printf("Address[%d] = %02x\n", i, addr[i]); + wolfBoot_printf("NVM_FLASH_WRITEONCE non-erased write detected at address %p!\n", addr); + wolfBoot_printf("Address[%d] = %02x\n", i, addr[i]); return -1; } #endif @@ -137,9 +138,9 @@ int hal_flash_write(uintptr_t address, const uint8_t *data, int len) int hal_flash_erase(uintptr_t address, int len) { /* implicit cast abide compiler warning */ - fprintf(stderr, "hal_flash_erase addr %p len %d\n", (void*)address, len); + wolfBoot_printf( "hal_flash_erase addr %p len %d\n", (void*)address, len); if (address == erasefail_address + WOLFBOOT_PARTITION_BOOT_ADDRESS) { - fprintf(stderr, "POWER FAILURE\n"); + wolfBoot_printf( "POWER FAILURE\n"); /* Corrupt page */ memset((void*)address, 0xEE, len); exit(0); @@ -156,7 +157,7 @@ void hal_init(void) ret = mmap_file(INTERNAL_FLASH_FILE, (uint8_t*)ARCH_FLASH_OFFSET, &sim_ram_base); if (ret != 0) { - fprintf(stderr, "failed to load internal flash file\n"); + wolfBoot_printf( "failed to load internal flash file\n"); exit(-1); } @@ -164,7 +165,7 @@ void hal_init(void) ret = mmap_file(EXTERNAL_FLASH_FILE, (uint8_t*)ARCH_FLASH_OFFSET + 0x10000000, &flash_base); if (ret != 0) { - fprintf(stderr, "failed to load external flash file\n"); + wolfBoot_printf( "failed to load external flash file\n"); exit(-1); } #endif /* EXT_FLASH */ @@ -172,7 +173,7 @@ void hal_init(void) for (i = 1; i < main_argc; i++) { if (strcmp(main_argv[i], "powerfail") == 0) { erasefail_address = strtol(main_argv[++i], NULL, 16); - fprintf(stderr, "Set power fail to erase at address %x\n", + wolfBoot_printf( "Set power fail to erase at address %x\n", erasefail_address); } /* force a bad write of the boot partition to trigger and test the @@ -262,7 +263,7 @@ void do_boot(const uint32_t *app_offset) ret = NSCreateObjectFileImageFromMemory(app_buf, app_size, &fileImage); if (ret != 1 || fileImage == NULL) { - fprintf(stderr, "Error loading object memory!\n"); + wolfBoot_printf( "Error loading object memory!\n"); exit(-1); } module = NSLinkModule(fileImage, "module", @@ -270,7 +271,7 @@ void do_boot(const uint32_t *app_offset) symbol = NSLookupSymbolInModule(module, "__mh_execute_header"); pSymbolAddress = NSAddressOfSymbol(symbol); if (!find_epc(pSymbolAddress, &epc)) { - fprintf(stderr, "Error finding entry point!\n"); + wolfBoot_printf( "Error finding entry point!\n"); exit(-1); } @@ -283,17 +284,17 @@ void do_boot(const uint32_t *app_offset) char *envp[1] = {NULL}; int fd = memfd_create("test_app", 0); if (fd == -1) { - fprintf(stderr, "memfd error\n"); + wolfBoot_printf( "memfd error\n"); exit(-1); } if ((size_t)write(fd, app_offset, app_size) != app_size) { - fprintf(stderr, "can't write test-app to memfd\n"); + wolfBoot_printf( "can't write test-app to memfd\n"); exit(-1); } ret = fexecve(fd, main_argv, envp); - fprintf(stderr, "fexecve error\n"); + wolfBoot_printf( "fexecve error\n"); #endif exit(1); } diff --git a/include/image.h b/include/image.h index 952df6daf..24960518a 100644 --- a/include/image.h +++ b/include/image.h @@ -79,7 +79,68 @@ int wolfBot_get_dts_size(void *dts_addr); #define SECT_FLAG_UPDATED 0x0f #endif +#ifdef WOLFBOOT_SIGN_PRIMARY_ED25519 +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_ed25519 +#endif +#ifdef WOLFBOOT_SIGN_PRIMARY_ED448 +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_ed448 +#endif +#if defined (WOLFBOOT_SIGN_PRIMARY_RSA2048) || \ + defined (WOLFBOOT_SIGN_PRIMARY_RSA3072) || \ + defined (WOLFBOOT_SIGN_PRIMARY_RSA4096) || \ + defined (WOLFBOOT_SIGN_PRIMARY_RSA2048ENC) || \ + defined (WOLFBOOT_SIGN_PRIMARY_RSA3072ENC) || \ + defined (WOLFBOOT_SIGN_PRIMARY_RSA4096ENC) +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_rsa +#endif +#if defined (WOLFBOOT_SIGN_PRIMARY_ECC256) || \ + defined (WOLFBOOT_SIGN_PRIMARY_ECC384) || \ + defined (WOLFBOOT_SIGN_PRIMARY_ECC521) +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_ecc +#endif +#if defined(WOLFBOOT_SIGN_PRIMARY_LMS) || defined(WOLFBOOT_SIGN_PRIMARY_ext_LMS) +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_lms +#endif +#if defined(WOLFBOOT_SIGN_PRIMARY_XMSS ) || defined(WOLFBOOT_SIGN_PRIMARY_ext_XMSS) +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_xmss +#endif +#ifdef WOLFBOOT_SIGN_PRIMARY_ML_DSA +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_ml_dsa +#endif + +#ifdef WOLFBOOT_SIGN_SECONDARY_ED25519 +#define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ed25519 +#endif +#ifdef WOLFBOOT_SIGN_SECONDARY_ED448 +#define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ed448 +#endif +#if defined (WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA2048ENC) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA3072ENC) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA4096ENC) +#define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_rsa +#endif +#if defined (WOLFBOOT_SIGN_SECONDARY_ECC256) || \ + defined (WOLFBOOT_SIGN_SECONDARY_ECC384) || \ + defined (WOLFBOOT_SIGN_SECONDARY_ECC521) +#define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ecc +#endif +#ifdef WOLFBOOT_SIGN_SECONDARY_LMS +#define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_lms +#endif +#ifdef WOLFBOOT_SIGN_SECONDARY_XMSS +#define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_xmss +#endif +#ifdef WOLFBOOT_SIGN_SECONDARY_ML_DSA +#define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ml_dsa +#endif +#if defined(WOLFBOOT_TPM) && defined (WOLFBOOT_TPM_VERIFY) +#undef wolfBoot_verify_signature_primary +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_tpm +#endif #if (defined(WOLFBOOT_ARMORED) && defined(__WOLFBOOT)) @@ -128,6 +189,16 @@ static void __attribute__((noinline)) wolfBoot_image_confirm_signature_ok( img->canary_FEED89AB = 0xFEED89ABUL; } +static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( + struct wolfBoot_image *img) +{ + img->canary_FEED4567 = 0xFEED4567UL; + img->signature_ok = 0UL; + img->canary_FEED6789 = 0xFEED6789UL; + img->not_signature_ok = 1UL; + img->canary_FEED89AB = 0xFEED89ABUL; +} + /** * Final sanity check, performed just before do_boot, or before starting an * update that has been verified. @@ -330,8 +401,8 @@ static void __attribute__((noinline)) wolfBoot_image_confirm_signature_ok( } /** - * ECC / Ed signature verification. - * ECC and Ed verify functions set an additional value 'p_res' + * ECC / Ed / PQ signature verification. + * Those verify functions set an additional value 'p_res' * which is passed as a pointer. * * Ensure that the verification function has been called, and then @@ -528,15 +599,14 @@ struct wolfBoot_image { }; /* do not warn if this is not used */ -#if !defined(__CCRX__) -static void __attribute__ ((unused)) wolfBoot_image_confirm_signature_ok( - struct wolfBoot_image *img) -#else static void wolfBoot_image_confirm_signature_ok(struct wolfBoot_image *img) -#endif { img->signature_ok = 1; } +static void wolfBoot_image_clear_signature_ok(struct wolfBoot_image *img) +{ + img->signature_ok = 0; +} #define likely(x) (x) #define unlikely(x) (x) diff --git a/include/keystore.h b/include/keystore.h index 4f0719e4b..1fa7dc59d 100644 --- a/include/keystore.h +++ b/include/keystore.h @@ -32,7 +32,11 @@ extern "C" { #ifndef KEYSTORE_PUBKEY_SIZE /* allow building version for external API use */ #define KEYSTORE_ANY - #define KEYSTORE_PUBKEY_SIZE 576 /* Max is RSA 4096 */ +#ifdef WOLFBOOT_SIGN_ML_DSA + #define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ML_DSA +#else + #define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA4096 +#endif #endif diff --git a/include/loader.h b/include/loader.h index f1b614fe5..80d327bcb 100644 --- a/include/loader.h +++ b/include/loader.h @@ -29,53 +29,29 @@ extern "C" { #endif -#if defined(WOLFBOOT_SIGN_ED25519) - extern const unsigned char ed25519_pub_key[]; - extern unsigned int ed25519_pub_key_len; -# define IMAGE_SIGNATURE_SIZE (64) -#elif defined(WOLFBOOT_SIGN_ED448) - extern const unsigned char ed448_pub_key[]; - extern unsigned int ed448_pub_key_len; -# define IMAGE_SIGNATURE_SIZE (114) -#elif defined(WOLFBOOT_SIGN_ECC256) - extern const unsigned char ecc256_pub_key[]; - extern unsigned int ecc256_pub_key_len; -# define IMAGE_SIGNATURE_SIZE (64) -#elif defined(WOLFBOOT_SIGN_ECC384) - extern const unsigned char ecc384_pub_key[]; - extern unsigned int ecc384_pub_key_len; -# define IMAGE_SIGNATURE_SIZE (96) -#elif defined(WOLFBOOT_SIGN_ECC521) - extern const unsigned char ecc521_pub_key[]; - extern unsigned int ecc521_pub_key_len; -# define IMAGE_SIGNATURE_SIZE (132) -#elif defined(WOLFBOOT_SIGN_RSA2048) - extern const unsigned char rsa2048_pub_key[]; - extern unsigned int rsa2048_pub_key_len; -# define IMAGE_SIGNATURE_SIZE (256) -#elif defined(WOLFBOOT_SIGN_RSA3072) - extern const unsigned char rsa3072_pub_key[]; - extern unsigned int rsa3072_pub_key_len; -# define IMAGE_SIGNATURE_SIZE (384) -#elif defined(WOLFBOOT_SIGN_RSA4096) - extern const unsigned char rsa4096_pub_key[]; - extern unsigned int rsa4096_pub_key_len; -# define IMAGE_SIGNATURE_SIZE (512) -/* In PQC methods the signature size is a function of - * the parameters. Therefore IMAGE_SIGNATURE_SIZE is - * set in options.mk from the .config file. */ -#elif defined(WOLFBOOT_SIGN_LMS) - extern const unsigned char lms_pub_key[]; - extern unsigned int lms_pub_key_len; -#elif defined(WOLFBOOT_SIGN_XMSS) - extern const unsigned char xmss_pub_key[]; - extern unsigned int xmss_pub_key_len; -#elif defined(WOLFBOOT_SIGN_ML_DSA) - extern const unsigned char ml_dsa_pub_key[]; - extern unsigned int ml_dsa_pub_key_len; -#elif !defined(WOLFBOOT_NO_SIGN) -# error "No public key available for given signing algorithm." -#endif /* Algorithm selection */ +#define ED25519_IMAGE_SIGNATURE_SIZE (64) +#define ED448_IMAGE_SIGNATURE_SIZE (114) + +#if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFBOOT_SECONDARY_SIGN_ECC256) +#define ECC_IMAGE_SIGNATURE_SIZE (64) +#elif defined(WOLFBOOT_SIGN_ECC384) || defined(WOLFBOOT_SECONDARY_SIGN_ECC384) +#define ECC_IMAGE_SIGNATURE_SIZE (96) +#elif defined(WOLFBOOT_SIGN_ECC521) || defined(WOLFBOOT_SECONDARY_SIGN_ECC521) +#define ECC_IMAGE_SIGNATURE_SIZE (132) +#endif + +#if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SECONDARY_SIGN_RSA2048) +#define RSA_IMAGE_SIGNATURE_SIZE (256) +#elif defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SECONDARY_SIGN_RSA3072) +#define RSA_IMAGE_SIGNATURE_SIZE (384) +#elif defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SECONDARY_SIGN_RSA4096) +#define RSA_IMAGE_SIGNATURE_SIZE (512) +#endif + +#ifndef ML_DSA_IMAGE_SIGNATURE_SIZE +#define ML_DSA_IMAGE_SIGNATURE_SIZE (3309) +#endif + void wolfBoot_start(void); diff --git a/include/user_settings.h b/include/user_settings.h index 188c4f19c..5ddaaab61 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -70,7 +70,7 @@ extern int tolower(int c); #endif /* ED25519 and SHA512 */ -#ifdef WOLFBOOT_SIGN_ED25519 +#if defined(WOLFBOOT_SIGN_ED25519) || defined(WOLFBOOT_SIGN_SECONDARY_ED25519) # define HAVE_ED25519 # define ED25519_SMALL # define NO_ED25519_SIGN @@ -80,7 +80,7 @@ extern int tolower(int c); #endif /* ED448 and SHA3/SHAKE256 */ -#ifdef WOLFBOOT_SIGN_ED448 +#if defined(WOLFBOOT_SIGN_ED448) || defined(WOLFBOOT_SIGN_SECONDARY_ED448) # define HAVE_ED448 # define HAVE_ED448_VERIFY # define ED448_SMALL @@ -94,8 +94,12 @@ extern int tolower(int c); #if defined(WOLFBOOT_SIGN_ECC256) || \ defined(WOLFBOOT_SIGN_ECC384) || \ defined(WOLFBOOT_SIGN_ECC521) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC256) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC384) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC521) || \ defined(WOLFCRYPT_SECURE_MODE) + # define HAVE_ECC # define ECC_TIMING_RESISTANT # define ECC_USER_CURVES /* enables only 256-bit by default */ @@ -141,12 +145,15 @@ extern int tolower(int c); /* Curve */ -# if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFCRYPT_SECURE_MODE) +# if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFCRYPT_SECURE_MODE) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC256) # define HAVE_ECC256 -# elif defined(WOLFBOOT_SIGN_ECC384) +# elif defined(WOLFBOOT_SIGN_ECC384) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC384) # define HAVE_ECC384 # define WOLFSSL_SP_384 -# elif defined(WOLFBOOT_SIGN_ECC521) +# elif defined(WOLFBOOT_SIGN_ECC521) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC521) # define HAVE_ECC521 # define WOLFSSL_SP_521 # endif @@ -175,13 +182,18 @@ extern int tolower(int c); # define WOLFSSL_SP_NO_256 # endif # endif -#endif /* WOLFBOOT_SIGN_ECC521 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC256 */ +#endif /* WOLFBOOT_SIGN_ECC521 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC256 || + * WOLFBOOT_SIGN_SECONDARY_ECC521 || WOLFBOOT_SIGN_SECONDARY_ECC384 || + * WOLFBOOT_SIGN_SECONDARY_ECC256 || WOLFCRYPT_SECURE_MODE */ /* RSA */ #if defined(WOLFBOOT_SIGN_RSA2048) || \ defined(WOLFBOOT_SIGN_RSA3072) || \ defined(WOLFBOOT_SIGN_RSA4096) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ (defined(WOLFCRYPT_SECURE_MODE) && (!defined(PKCS11_SMALL))) # define WC_RSA_BLINDING @@ -200,20 +212,20 @@ extern int tolower(int c); # define WOLFSSL_SP_SMALL # define WOLFSSL_SP_MATH # endif -# ifdef WOLFBOOT_SIGN_RSA2048 +# if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) # define FP_MAX_BITS (2048 * 2) # define WOLFSSL_SP_NO_3072 # define WOLFSSL_SP_NO_4096 # define WOLFSSL_SP_2048 # endif -# ifdef WOLFBOOT_SIGN_RSA3072 +# if defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) # define FP_MAX_BITS (3072 * 2) # define WOLFSSL_SP_NO_2048 # define WOLFSSL_SP_NO_4096 # define WOLFSSL_SP_3072 # endif -# ifdef WOLFBOOT_SIGN_RSA4096 +# if defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) # define FP_MAX_BITS (4096 * 2) # define WOLFSSL_SP_NO_2048 # define WOLFSSL_SP_NO_3072 @@ -231,7 +243,7 @@ extern int tolower(int c); #endif /* RSA */ /* ML-DSA (dilithium) */ -#if defined(WOLFBOOT_SIGN_ML_DSA) +#if defined(WOLFBOOT_SIGN_ML_DSA) || defined(WOLFBOOT_SIGN_SECONDARY_ML_DSA) # define HAVE_DILITHIUM # define WOLFSSL_WC_DILITHIUM # define WOLFSSL_EXPERIMENTAL_SETTINGS @@ -251,7 +263,7 @@ extern int tolower(int c); # define WOLFSSL_SHA3 # define WOLFSSL_SHAKE256 # define WOLFSSL_SHAKE128 -#endif /* WOLFBOOT_SIGN_ML_DSA */ +#endif /* WOLFBOOT_SIGN_ML_DSA || WOLFBOOT_SIGN_SECONDARY_ML_DSA */ #ifdef WOLFBOOT_HASH_SHA3_384 # define WOLFSSL_SHA3 @@ -308,6 +320,7 @@ extern int tolower(int c); # define WOLFSSL_AES_COUNTER # define WOLFSSL_AES_DIRECT # define WOLFSSL_AES_GCM +# define GCM_TABLE_4BIT # define ENCRYPT_WITH_AES128 # define WOLFSSL_AES_128 # define HAVE_SCRYPT @@ -497,9 +510,6 @@ extern int tolower(int c); #define RENESAS_DEVID 7890 #endif #endif - - - #endif /* WOLFBOOT_PKCS11_APP */ #ifndef XTOLOWER diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index d404f5c62..00131bc07 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -67,12 +67,15 @@ extern "C" { #define HDR_IMG_DELTA_BASE 0x05 #define HDR_IMG_DELTA_SIZE 0x06 #define HDR_PUBKEY 0x10 +#define HDR_SECONDARY_CIPHER 0x11 +#define HDR_SECONDARY_PUBKEY 0x12 #define HDR_SHA3_384 0x13 #define HDR_SHA384 0x14 #define HDR_IMG_DELTA_INVERSE 0x15 #define HDR_IMG_DELTA_INVERSE_SIZE 0x16 #define HDR_SIGNATURE 0x20 #define HDR_POLICY_SIGNATURE 0x21 +#define HDR_SECONDARY_SIGNATURE 0x22 #define HDR_PADDING 0xFF /* Auth Key types */ @@ -85,11 +88,10 @@ extern "C" { #define AUTH_KEY_ECC521 0x07 #define AUTH_KEY_RSA3072 0x08 #define AUTH_KEY_LMS 0x09 + /* 0x0A...0x0F reserved */ #define AUTH_KEY_XMSS 0x10 #define AUTH_KEY_ML_DSA 0x11 - - /* * 8 bits: auth type * 4 bits: extra features @@ -118,72 +120,71 @@ extern "C" { #define HDR_IMG_TYPE_APP 0x0001 #endif - #define KEYSTORE_PUBKEY_SIZE_NONE 0 - #define KEYSTORE_PUBKEY_SIZE_ED25519 32 - #define KEYSTORE_PUBKEY_SIZE_ED448 57 - #define KEYSTORE_PUBKEY_SIZE_ECC256 64 - #define KEYSTORE_PUBKEY_SIZE_ECC384 96 - #define KEYSTORE_PUBKEY_SIZE_ECC521 132 - #define KEYSTORE_PUBKEY_SIZE_RSA2048 320 - #define KEYSTORE_PUBKEY_SIZE_RSA3072 448 - #define KEYSTORE_PUBKEY_SIZE_RSA4096 576 - #define KEYSTORE_PUBKEY_SIZE_LMS 60 - #define KEYSTORE_PUBKEY_SIZE_XMSS 68 - /* ML-DSA pub key size is a function of parameters. - * This needs to be configurable. Default to security - * category 2. */ - #ifdef ML_DSA_LEVEL - #if ML_DSA_LEVEL == 2 - #define KEYSTORE_PUBKEY_SIZE_ML_DSA 1312 - #elif ML_DSA_LEVEL == 3 - #define KEYSTORE_PUBKEY_SIZE_ML_DSA 1952 - #elif ML_DSA_LEVEL == 5 - #define KEYSTORE_PUBKEY_SIZE_ML_DSA 2592 - #else - #error "Invalid ML_DSA_LEVEL!" - #endif - #else - #define KEYSTORE_PUBKEY_SIZE_ML_DSA 1312 - #endif /* ML_DSA_LEVEL */ +#define KEYSTORE_PUBKEY_SIZE_NONE 0 +#define KEYSTORE_PUBKEY_SIZE_ED25519 32 +#define KEYSTORE_PUBKEY_SIZE_ED448 57 +#define KEYSTORE_PUBKEY_SIZE_ECC256 64 +#define KEYSTORE_PUBKEY_SIZE_ECC384 96 +#define KEYSTORE_PUBKEY_SIZE_ECC521 132 +#define KEYSTORE_PUBKEY_SIZE_RSA2048 320 +#define KEYSTORE_PUBKEY_SIZE_RSA3072 448 +#define KEYSTORE_PUBKEY_SIZE_RSA4096 576 +#define KEYSTORE_PUBKEY_SIZE_LMS 60 +#define KEYSTORE_PUBKEY_SIZE_XMSS 68 + +/* ML-DSA pub key size is a function of parameters. + * This needs to be configurable. Default to security + * category 2. */ +#ifdef ML_DSA_LEVEL + #if ML_DSA_LEVEL == 2 + #define KEYSTORE_PUBKEY_SIZE_ML_DSA 1312 + #elif ML_DSA_LEVEL == 3 + #define KEYSTORE_PUBKEY_SIZE_ML_DSA 1952 + #elif ML_DSA_LEVEL == 5 + #define KEYSTORE_PUBKEY_SIZE_ML_DSA 2592 + #else + #error "Invalid ML_DSA_LEVEL!" + #endif +#endif /* ML_DSA_LEVEL */ /* Mask for key permissions */ - #define KEY_VERIFY_ALL (0xFFFFFFFFU) - #define KEY_VERIFY_ONLY_ID(X) (1U << X) - #define KEY_VERIFY_SELF_ONLY KEY_VERIFY_ONLY_ID(0) - #define KEY_VERIFY_APP_ONLY KEY_VERIFY_ONLY_ID(1) +#define KEY_VERIFY_ALL (0xFFFFFFFFU) +#define KEY_VERIFY_ONLY_ID(X) (1U << X) +#define KEY_VERIFY_SELF_ONLY KEY_VERIFY_ONLY_ID(0) +#define KEY_VERIFY_APP_ONLY KEY_VERIFY_ONLY_ID(1) #if defined(__WOLFBOOT) || defined(UNIT_TEST_AUTH) - /* Hashing configuration */ - #if defined(WOLFBOOT_HASH_SHA256) - # ifndef WOLFBOOT_SHA_BLOCK_SIZE - # define WOLFBOOT_SHA_BLOCK_SIZE (256) - # endif - # define WOLFBOOT_SHA_HDR HDR_SHA256 - # define WOLFBOOT_SHA_DIGEST_SIZE (32) - # define image_hash image_sha256 - # define key_hash key_sha256 - # define self_hash self_sha256 - #elif defined(WOLFBOOT_HASH_SHA384) - # ifndef WOLFBOOT_SHA_BLOCK_SIZE - # define WOLFBOOT_SHA_BLOCK_SIZE (256) - # endif - # define WOLFBOOT_SHA_HDR HDR_SHA384 - # define WOLFBOOT_SHA_DIGEST_SIZE (48) - # define image_hash image_sha384 - # define key_hash key_sha384 - # define self_hash self_sha384 - #elif defined(WOLFBOOT_HASH_SHA3_384) - # ifndef WOLFBOOT_SHA_BLOCK_SIZE - # define WOLFBOOT_SHA_BLOCK_SIZE (128) - # endif - # define WOLFBOOT_SHA_HDR HDR_SHA3_384 - # define WOLFBOOT_SHA_DIGEST_SIZE (48) - # define image_hash image_sha3_384 - # define key_hash key_sha3_384 - #else - # error "No valid hash algorithm defined!" - #endif +/* Hashing configuration */ +#if defined(WOLFBOOT_HASH_SHA256) +# ifndef WOLFBOOT_SHA_BLOCK_SIZE +# define WOLFBOOT_SHA_BLOCK_SIZE (256) +# endif +# define WOLFBOOT_SHA_HDR HDR_SHA256 +# define WOLFBOOT_SHA_DIGEST_SIZE (32) +# define image_hash image_sha256 +# define key_hash key_sha256 +# define self_hash self_sha256 +#elif defined(WOLFBOOT_HASH_SHA384) +# ifndef WOLFBOOT_SHA_BLOCK_SIZE +# define WOLFBOOT_SHA_BLOCK_SIZE (256) +# endif +# define WOLFBOOT_SHA_HDR HDR_SHA384 +# define WOLFBOOT_SHA_DIGEST_SIZE (48) +# define image_hash image_sha384 +# define key_hash key_sha384 +# define self_hash self_sha384 +#elif defined(WOLFBOOT_HASH_SHA3_384) +# ifndef WOLFBOOT_SHA_BLOCK_SIZE +# define WOLFBOOT_SHA_BLOCK_SIZE (128) +# endif +# define WOLFBOOT_SHA_HDR HDR_SHA3_384 +# define WOLFBOOT_SHA_DIGEST_SIZE (48) +# define image_hash image_sha3_384 +# define key_hash key_sha3_384 +#else +# error "No valid hash algorithm defined!" +#endif #ifdef WOLFBOOT_TPM #if defined(WOLFBOOT_HASH_SHA256) @@ -197,7 +198,7 @@ extern "C" { #endif -#if defined(__WOLFBOOT) || defined (__FLASH_OTP_PRIMER) || defined (UNIT_TEST_AUTH) +#if defined(__WOLFBOOT) || defined (__FLASH_OTP_PRIMER) || defined (UNIT_TEST_AUTH) || defined(WOLFBOOT_TPM) /* Authentication configuration */ #if defined(WOLFBOOT_NO_SIGN) @@ -230,17 +231,17 @@ extern "C" { # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE # define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ECC521 # endif - #elif defined(WOLFBOOT_SIGN_RSA2048) + #elif defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_RSA2048ENC) # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSA2048 # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE # define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA2048 # endif - #elif defined(WOLFBOOT_SIGN_RSA3072) + #elif defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_RSA3072ENC) # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSA3072 # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE # define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA3072 # endif - #elif defined(WOLFBOOT_SIGN_RSA4096) + #elif defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_RSA4096ENC) # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSA4096 # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE # define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA4096 @@ -269,7 +270,6 @@ extern "C" { #endif /* defined WOLFBOOT */ - #define PART_BOOT 0 #define PART_UPDATE 1 #define PART_SWAP 2 diff --git a/options.mk b/options.mk index 4600679fe..73da75430 100644 --- a/options.mk +++ b/options.mk @@ -71,16 +71,63 @@ ifeq ($(WOLFBOOT_SMALL_STACK),1) OBJS+=./src/xmalloc.o endif + +ECC_OBJS= \ + ./lib/wolfssl/wolfcrypt/src/ecc.o + +ED25519_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/fe_low_mem.o + +ED448_OBJS=./lib/wolfssl/wolfcrypt/src/ed448.o \ + ./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \ + ./lib/wolfssl/wolfcrypt/src/ge_448.o \ + ./lib/wolfssl/wolfcrypt/src/fe_448.o \ + ./lib/wolfssl/wolfcrypt/src/fe_low_mem.o + +RSA_OBJS=\ + $(RSA_EXTRA_OBJS) \ + ./lib/wolfssl/wolfcrypt/src/rsa.o + +LMS_OBJS=\ + ./lib/wolfssl/wolfcrypt/src/wc_lms.o \ + ./lib/wolfssl/wolfcrypt/src/wc_lms_impl.o + +LMS_EXTRA=\ + -D"WOLFSSL_HAVE_LMS" \ + -D"WOLFSSL_WC_LMS" -D"WOLFSSL_WC_LMS_SMALL" \ + -D"WOLFSSL_LMS_MAX_LEVELS=$(LMS_LEVELS)" \ + -D"WOLFSSL_LMS_MAX_HEIGHT=$(LMS_HEIGHT)" \ + -D"LMS_LEVELS=$(LMS_LEVELS)" -D"LMS_HEIGHT=$(LMS_HEIGHT)" \ + -D"LMS_WINTERNITZ=$(LMS_WINTERNITZ)" \ + -D"LMS_IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \ + -D"WOLFSSL_LMS_VERIFY_ONLY" + +XMSS_OBJS=\ + ./lib/wolfssl/wolfcrypt/src/wc_xmss.o \ + ./lib/wolfssl/wolfcrypt/src/wc_xmss_impl.o + +XMSS_EXTRA=\ + -D"WOLFSSL_HAVE_XMSS" \ + -D"WOLFSSL_WC_XMSS" -D"WOLFSSL_WC_XMSS_SMALL" \ + -DWOLFBOOT_XMSS_PARAMS=\"$(XMSS_PARAMS)\" \ + -D"XMSS_IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \ + -D"WOLFSSL_XMSS_VERIFY_ONLY" -D"WOLFSSL_XMSS_MAX_HEIGHT=32" + +ML_DSA_OBJS=\ + ./lib/wolfssl/wolfcrypt/src/dilithium.o \ + ./lib/wolfssl/wolfcrypt/src/memory.o + +ML_DSA_EXTRA=\ + -D"ML_DSA_IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \ + -D"ML_DSA_LEVEL"=$(ML_DSA_LEVEL) + ifeq ($(SIGN),ECC256) KEYGEN_OPTIONS+=--ecc256 SIGN_OPTIONS+=--ecc256 - WOLFCRYPT_OBJS+= \ - $(MATH_OBJS) \ - ./lib/wolfssl/wolfcrypt/src/ecc.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o + WOLFCRYPT_OBJS+=$(ECC_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) CFLAGS+=-D"WOLFBOOT_SIGN_ECC256" ifeq ($(WOLFBOOT_SMALL_STACK),1) STACK_USAGE=4096 @@ -103,13 +150,8 @@ endif ifeq ($(SIGN),ECC384) KEYGEN_OPTIONS+=--ecc384 SIGN_OPTIONS+=--ecc384 - WOLFCRYPT_OBJS+= \ - $(MATH_OBJS) \ - ./lib/wolfssl/wolfcrypt/src/ecc.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o + WOLFCRYPT_OBJS+=$(ECC_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) CFLAGS+=-D"WOLFBOOT_SIGN_ECC384" ifeq ($(WOLFBOOT_SMALL_STACK),1) STACK_USAGE=5880 @@ -132,14 +174,9 @@ endif ifeq ($(SIGN),ECC521) KEYGEN_OPTIONS+=--ecc521 SIGN_OPTIONS+=--ecc521 - WOLFCRYPT_OBJS+= \ - $(MATH_OBJS) \ - ./lib/wolfssl/wolfcrypt/src/ecc.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o CFLAGS+=-D"WOLFBOOT_SIGN_ECC521" + WOLFCRYPT_OBJS+=$(ECC_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) ifeq ($(WOLFBOOT_SMALL_STACK),1) STACK_USAGE=4096 else @@ -162,13 +199,7 @@ endif ifeq ($(SIGN),ED25519) KEYGEN_OPTIONS+=--ed25519 SIGN_OPTIONS+=--ed25519 - WOLFCRYPT_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/hash.o \ - ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/fe_low_mem.o + WOLFCRYPT_OBJS+=$(ED25519_OBJS) CFLAGS+=-D"WOLFBOOT_SIGN_ED25519" ifeq ($(WOLFTPM),1) STACK_USAGE=6680 @@ -183,14 +214,7 @@ endif ifeq ($(SIGN),ED448) KEYGEN_OPTIONS+=--ed448 SIGN_OPTIONS+=--ed448 - WOLFCRYPT_OBJS+= ./lib/wolfssl/wolfcrypt/src/ed448.o \ - ./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \ - ./lib/wolfssl/wolfcrypt/src/ge_448.o \ - ./lib/wolfssl/wolfcrypt/src/fe_448.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o \ - ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/fe_low_mem.o + WOLFCRYPT_OBJS+= $(ED448_OBJS) ifeq ($(WOLFTPM),1) STACK_USAGE=6680 else @@ -219,14 +243,8 @@ ifneq ($(findstring RSA2048,$(SIGN)),) SIGN_OPTIONS+=--rsa2048 endif SIGN_ALG=RSA2048 # helps keystore.c check - WOLFCRYPT_OBJS+= \ - $(RSA_EXTRA_OBJS) \ - $(MATH_OBJS) \ - ./lib/wolfssl/wolfcrypt/src/rsa.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o + WOLFCRYPT_OBJS+= $(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) CFLAGS+=-D"WOLFBOOT_SIGN_RSA2048" $(RSA_EXTRA_CFLAGS) ifeq ($(WOLFBOOT_SMALL_STACK),1) ifneq ($(SPMATH),1) @@ -258,14 +276,8 @@ ifneq ($(findstring RSA3072,$(SIGN)),) SIGN_OPTIONS+=--rsa3072 endif SIGN_ALG=RSA3072 # helps keystore.c check - WOLFCRYPT_OBJS+= \ - $(RSA_EXTRA_OBJS) \ - $(MATH_OBJS) \ - ./lib/wolfssl/wolfcrypt/src/rsa.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o + WOLFCRYPT_OBJS+= $(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) CFLAGS+=-D"WOLFBOOT_SIGN_RSA3072" $(RSA_EXTRA_CFLAGS) ifeq ($(WOLFBOOT_SMALL_STACK),1) ifneq ($(SPMATH),1) @@ -301,14 +313,8 @@ ifneq ($(findstring RSA4096,$(SIGN)),) SIGN_OPTIONS+=--rsa4096 endif SIGN_ALG=RSA4096 # helps keystore.c check - WOLFCRYPT_OBJS+= \ - $(RSA_EXTRA_OBJS) \ - $(MATH_OBJS) \ - ./lib/wolfssl/wolfcrypt/src/rsa.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o + WOLFCRYPT_OBJS+= $(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) CFLAGS+=-D"WOLFBOOT_SIGN_RSA4096" $(RSA_EXTRA_CFLAGS) ifeq ($(WOLFBOOT_SMALL_STACK),1) ifneq ($(SPMATH),1) @@ -362,20 +368,8 @@ endif ifeq ($(SIGN),LMS) KEYGEN_OPTIONS+=--lms SIGN_OPTIONS+=--lms - WOLFCRYPT_OBJS+= \ - ./lib/wolfssl/wolfcrypt/src/wc_lms.o \ - ./lib/wolfssl/wolfcrypt/src/wc_lms_impl.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o - CFLAGS+=-D"WOLFBOOT_SIGN_LMS" -D"WOLFSSL_HAVE_LMS" \ - -D"WOLFSSL_WC_LMS" -D"WOLFSSL_WC_LMS_SMALL" \ - -D"WOLFSSL_LMS_MAX_LEVELS=$(LMS_LEVELS)" \ - -D"WOLFSSL_LMS_MAX_HEIGHT=$(LMS_HEIGHT)" \ - -D"LMS_LEVELS=$(LMS_LEVELS)" -D"LMS_HEIGHT=$(LMS_HEIGHT)" \ - -D"LMS_WINTERNITZ=$(LMS_WINTERNITZ)" \ - -D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \ - -D"WOLFSSL_LMS_VERIFY_ONLY" + WOLFCRYPT_OBJS+= $(LMS_OBJS) + CFLAGS+=-D"WOLFBOOT_SIGN_LMS" $(LMS_EXTRA) ifeq ($(WOLFBOOT_SMALL_STACK),1) $(error WOLFBOOT_SMALL_STACK with LMS not supported) else @@ -387,6 +381,7 @@ ifeq ($(SIGN),ext_LMS) LMSDIR = lib/hash-sigs KEYGEN_OPTIONS+=--lms SIGN_OPTIONS+=--lms + CFLAGS+=-D"LMS_IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) WOLFCRYPT_OBJS+= \ ./$(LMSDIR)/src/hss_verify.o \ ./$(LMSDIR)/src/hss_verify_inc.o \ @@ -400,10 +395,7 @@ ifeq ($(SIGN),ext_LMS) ./$(LMSDIR)/src/endian.o \ ./$(LMSDIR)/src/hash.o \ ./$(LMSDIR)/src/sha256.o \ - ./lib/wolfssl/wolfcrypt/src/ext_lms.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o + ./lib/wolfssl/wolfcrypt/src/ext_lms.o CFLAGS+=-D"WOLFBOOT_SIGN_LMS" -D"WOLFSSL_HAVE_LMS" -D"HAVE_LIBLMS" \ -D"LMS_LEVELS=$(LMS_LEVELS)" -D"LMS_HEIGHT=$(LMS_HEIGHT)" \ -D"LMS_WINTERNITZ=$(LMS_WINTERNITZ)" -I$(LMSDIR)/src \ @@ -434,17 +426,9 @@ ifeq ($(SIGN),XMSS) # Use wc_xmss implementation. KEYGEN_OPTIONS+=--xmss SIGN_OPTIONS+=--xmss - WOLFCRYPT_OBJS+= \ - ./lib/wolfssl/wolfcrypt/src/wc_xmss.o \ - ./lib/wolfssl/wolfcrypt/src/wc_xmss_impl.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o - CFLAGS+=-D"WOLFBOOT_SIGN_XMSS" -D"WOLFSSL_HAVE_XMSS" \ - -D"WOLFSSL_WC_XMSS" -D"WOLFSSL_WC_XMSS_SMALL" \ - -DWOLFBOOT_XMSS_PARAMS=\"$(XMSS_PARAMS)\" \ - -D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \ - -D"WOLFSSL_XMSS_VERIFY_ONLY" -D"WOLFSSL_XMSS_MAX_HEIGHT=32" + WOLFCRYPT_OBJS+=$(XMSS_OBJS) + CFLAGS+=-D"WOLFBOOT_SIGN_XMSS" + CFLAGS+=$(XMSS_EXTRA) ifeq ($(WOLFBOOT_SMALL_STACK),1) $(error WOLFBOOT_SMALL_STACK with XMSS not supported) else @@ -457,6 +441,7 @@ ifeq ($(SIGN),ext_XMSS) XMSSDIR = lib/xmss KEYGEN_OPTIONS+=--xmss SIGN_OPTIONS+=--xmss + CFLAGS+=-D"XMSS_IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) WOLFCRYPT_OBJS+= \ ./$(XMSSDIR)/params.o \ ./$(XMSSDIR)/thash.o \ @@ -466,10 +451,7 @@ ifeq ($(SIGN),ext_XMSS) ./$(XMSSDIR)/xmss_core_fast.o \ ./$(XMSSDIR)/xmss_commons.o \ ./$(XMSSDIR)/utils.o \ - ./lib/wolfssl/wolfcrypt/src/ext_xmss.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o + ./lib/wolfssl/wolfcrypt/src/ext_xmss.o CFLAGS+=-D"WOLFBOOT_SIGN_XMSS" -D"WOLFSSL_HAVE_XMSS" -D"HAVE_LIBXMSS" \ -DWOLFBOOT_XMSS_PARAMS=\"$(XMSS_PARAMS)\" -I$(XMSSDIR) \ -D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \ @@ -491,15 +473,12 @@ ifeq ($(SIGN),ML_DSA) # Use wolfcrypt ML-DSA dilithium implementation. KEYGEN_OPTIONS+=--ml_dsa SIGN_OPTIONS+=--ml_dsa - WOLFCRYPT_OBJS+= \ - ./lib/wolfssl/wolfcrypt/src/dilithium.o \ - ./lib/wolfssl/wolfcrypt/src/memory.o \ - ./lib/wolfssl/wolfcrypt/src/sha3.o \ - ./lib/wolfssl/wolfcrypt/src/wc_port.o \ - ./lib/wolfssl/wolfcrypt/src/hash.o - CFLAGS+=-D"WOLFBOOT_SIGN_ML_DSA" \ - -D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \ - -D"ML_DSA_LEVEL"=$(ML_DSA_LEVEL) + WOLFCRYPT_OBJS+= $(ML_DSA_OBJS) + CFLAGS+=-D"WOLFBOOT_SIGN_ML_DSA" $(ML_DSA_EXTRA) + ifneq ($(HASH),SHA3) + WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/sha3.o + endif + ifeq ($(WOLFBOOT_SMALL_STACK),1) $(error WOLFBOOT_SMALL_STACK with ML-DSA not supported yet) else @@ -507,6 +486,62 @@ ifeq ($(SIGN),ML_DSA) endif endif +ifneq ($(SIGN_SECONDARY),) + LOWERCASE_SECONDARY=$(shell echo $(SIGN_SECONDARY) | tr '[:upper:]' '[:lower:]') + SECONDARY_KEYGEN_OPTIONS=--$(LOWERCASE_SECONDARY) + SECONDARY_SIGN_OPTIONS=--$(LOWERCASE_SECONDARY) + CFLAGS+=-DSIGN_HYBRID + CFLAGS+=-DWOLFBOOT_SIGN_SECONDARY_$(SIGN_SECONDARY) + ifeq ($(SIGN_SECONDARY),RSA2048) + WOLFCRYPT_OBJS+=$(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + ifeq ($(SIGN_SECONDARY),RSA3072) + WOLFCRYPT_OBJS+=$(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + ifeq ($(SIGN_SECONDARY),RSA4096) + WOLFCRYPT_OBJS+=$(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + ifeq ($(SIGN_SECONDARY),ECC256) + WOLFCRYPT_OBJS+=$(ECC_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + ifeq ($(SIGN_SECONDARY),ECC384) + WOLFCRYPT_OBJS+=$(ECC_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + ifeq ($(SIGN_SECONDARY),ECC521) + WOLFCRYPT_OBJS+=$(ECC_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + ifeq ($(SIGN_SECONDARY),ED25519) + WOLFCRYPT_OBJS+=$(ED25519_OBJS) + endif + ifeq ($(SIGN_SECONDARY),ED448) + WOLFCRYPT_OBJS+=$(ED448_OBJS) + endif + ifeq ($(SIGN_SECONDARY),LMS) + WOLFCRYPT_OBJS+=$(LMS_OBJS) + CFLAGS+=-D"WOLFBOOT_SIGN_LMS" $(LMS_EXTRA) + endif + ifeq ($(SIGN_SECONDARY),XMSS) + WOLFCRYPT_OBJS+= $(XMSS_OBJS) + CFLAGS+=-D"WOLFBOOT_SIGN_XMSS" $(XMSS_EXTRA) + endif + ifeq ($(SIGN_SECONDARY),ML_DSA) + WOLFCRYPT_OBJS+= $(ML_DSA_OBJS) + ifneq ($(HASH),SHA3) + WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/sha3.o + endif + CFLAGS+=-D"WOLFBOOT_SIGN_ML_DSA" $(ML_DSA_EXTRA) + endif +endif + + +CFLAGS+=-DWOLFBOOT_SIGN_PRIMARY_$(SIGN) + ifeq ($(RAM_CODE),1) CFLAGS+= -D"RAM_CODE" endif @@ -678,11 +713,14 @@ ifeq ($(WOLFCRYPT_TZ_PKCS11),1) CFLAGS+=-DCK_CALLABLE="__attribute__((cmse_nonsecure_entry))" CFLAGS+=-Ilib/wolfPKCS11 CFLAGS+=-DWP11_HASH_PIN_COST=3 - OBJS+=src/pkcs11_store.o - OBJS+=src/pkcs11_callable.o + WOLFCRYPT_OBJS+=src/pkcs11_store.o + WOLFCRYPT_OBJS+=src/pkcs11_callable.o WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/pwdbased.o WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/hmac.o WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/dh.o + ifeq ($(findstring random.o,$(WOLFCRYPT_OBJS)),) + WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/random.o + endif WOLFCRYPT_OBJS+=./lib/wolfPKCS11/src/crypto.o \ ./lib/wolfPKCS11/src/internal.o \ ./lib/wolfPKCS11/src/slot.o \ @@ -692,15 +730,23 @@ ifeq ($(WOLFCRYPT_TZ_PKCS11),1) WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/aes.o endif ifeq ($(findstring RSA,$(SIGN)),) - WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/rsa.o + ifeq ($(findstring RSA,$(SIGN_SECONDARY)),) + WOLFCRYPT_OBJS+=$(RSA_OBJS) + endif endif ifeq ($(findstring ECC,$(SIGN)),) - WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/ecc.o + ifeq ($(findstring ECC,$(SIGN_SECONDARY)),) + WOLFCRYPT_OBJS+=$(ECC_OBJS) + endif endif + ifeq ($(findstring ECC,$(SIGN)),) + ifeq ($(findstring ECC,$(SIGN_SECONDARY)),) ifeq ($(findstring RSA,$(SIGN)),) - ifeq ($(findstring ECC,$(SIGN)),) - WOLFCRYPT_OBJS+=$(MATH_OBJS) ./lib/wolfssl/wolfcrypt/src/wolfmath.o - endif + ifeq ($(findstring RSA,$(SIGN_SECONDARY)),) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + endif + endif endif endif @@ -845,7 +891,7 @@ ifeq ($(FLASH_MULTI_SECTOR_ERASE),1) endif CFLAGS+=$(CFLAGS_EXTRA) -OBJS:=$(OBJS_EXTRA) $(OBJS) +OBJS+=$(OBJS_EXTRA) ifeq ($(USE_GCC_HEADLESS),1) ifneq ($(ARCH),RENESAS_RX) diff --git a/src/image.c b/src/image.c index 6913e265d..329b55126 100644 --- a/src/image.c +++ b/src/image.c @@ -42,13 +42,28 @@ #ifdef WOLFBOOT_TPM #include "tpm.h" #endif +#ifdef WOLFBOOT_HASH_SHA256 +#include +#endif +#ifdef WOLFBOOT_HASH_SHA384 +#include +#endif +#ifdef WOLFBOOT_HASH_SHA3_384 +#include +#endif /* Globals */ static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE]; /* TPM based verify */ #if defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY) -static void wolfBoot_verify_signature(uint8_t key_slot, +#ifdef ECC_IMAGE_SIGNATURE_SIZE +#define IMAGE_SIGNATURE_SIZE ECC_IMAGE_SIGNATURE_SIZE +#else +#define IMAGE_SIGNATURE_SIZE RSA_IMAGE_SIGNATURE_SIZE +#endif + +static void wolfBoot_verify_signature_tpm(uint8_t key_slot, struct wolfBoot_image *img, uint8_t *sig) { int ret = 0, verify_res = 0; @@ -71,7 +86,8 @@ static void wolfBoot_verify_signature(uint8_t key_slot, if (ret == 0) { sigAlg = (alg == TPM_ALG_RSA) ? TPM_ALG_RSASSA : TPM_ALG_ECDSA; ret = wolfTPM2_VerifyHashScheme(&wolftpm_dev, &tpmKey, - sig, IMAGE_SIGNATURE_SIZE, /* Signature */ + sig, /* Signature */ + IMAGE_SIGNATURE_SIZE, /* Signature size */ img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, /* Hash */ sigAlg, WOLFBOOT_TPM_HASH_ALG); } @@ -97,7 +113,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, /* wolfCrypt software verify */ #ifdef WOLFBOOT_SIGN_ED25519 #include -static void wolfBoot_verify_signature(uint8_t key_slot, +static void wolfBoot_verify_signature_ed25519(uint8_t key_slot, struct wolfBoot_image *img, uint8_t *sig) { int ret, res; @@ -113,7 +129,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, /* Failed to import ed25519 key */ return; } - VERIFY_FN(img, &res, wc_ed25519_verify_msg, sig, IMAGE_SIGNATURE_SIZE, + VERIFY_FN(img, &res, wc_ed25519_verify_msg, sig, ED25519_IMAGE_SIGNATURE_SIZE, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &res, &ed); } @@ -121,7 +137,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, #ifdef WOLFBOOT_SIGN_ED448 #include -static void wolfBoot_verify_signature(uint8_t key_slot, +static void wolfBoot_verify_signature_ed448(uint8_t key_slot, struct wolfBoot_image *img, uint8_t *sig) { int ret, res; @@ -137,25 +153,27 @@ static void wolfBoot_verify_signature(uint8_t key_slot, /* Failed to import ed448 key */ return; } - VERIFY_FN(img, &res, wc_ed448_verify_msg, sig, IMAGE_SIGNATURE_SIZE, + VERIFY_FN(img, &res, wc_ed448_verify_msg, sig, ED448_IMAGE_SIGNATURE_SIZE, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &res, &ed, NULL, 0); } - #endif #if defined(WOLFBOOT_SIGN_ECC256) || \ defined(WOLFBOOT_SIGN_ECC384) || \ - defined(WOLFBOOT_SIGN_ECC521) + defined(WOLFBOOT_SIGN_ECC521) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC256) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC384) || \ + defined(WOLFBOOT_SIGN_SECONDARY_ECC521) #include -#if defined(WOLFBOOT_SIGN_ECC256) +#if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFBOOT_SIGN_SECONDARY_ECC256) #define ECC_KEY_TYPE ECC_SECP256R1 -#elif defined(WOLFBOOT_SIGN_ECC384) +#elif defined(WOLFBOOT_SIGN_ECC384) || defined(WOLFBOOT_SIGN_SECONDARY_ECC384) #define ECC_KEY_TYPE ECC_SECP384R1 -#elif defined(WOLFBOOT_SIGN_ECC521) +#elif defined(WOLFBOOT_SIGN_ECC521) || defined(WOLFBOOT_SIGN_SECONDARY_ECC521) #define ECC_KEY_TYPE ECC_SECP521R1 #endif @@ -167,7 +185,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, * @param img The image to verify. * @param sig The signature to use for verification. */ -static void wolfBoot_verify_signature(uint8_t key_slot, +static void wolfBoot_verify_signature_ecc(uint8_t key_slot, struct wolfBoot_image *img, uint8_t *sig) { int ret, verify_res = 0; @@ -201,7 +219,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, * trigger crypto callback. Building with NO_ASN allows us to send R+S * directly without ASN.1 encoded DSA header */ VERIFY_FN(img, &verify_res, wc_ecc_verify_hash, - sig, IMAGE_SIGNATURE_SIZE, + sig, ECC_IMAGE_SIGNATURE_SIZE, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &verify_res, &ecc) #else /* Import public key */ @@ -221,12 +239,17 @@ static void wolfBoot_verify_signature(uint8_t key_slot, wc_ecc_free(&ecc); } -#endif /* WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC521 */ +#endif /* WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC521 || + * WOLFBOOT_SIGN_SECONDARY_ECC256 || WOLFBOOT_SIGN_SECONDARY_ECC384 || + * WOLFBOOT_SIGN_SECONDARY_ECC521 */ #if defined(WOLFBOOT_SIGN_RSA2048) || \ defined(WOLFBOOT_SIGN_RSA3072) || \ - defined(WOLFBOOT_SIGN_RSA4096) + defined(WOLFBOOT_SIGN_RSA4096) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) #include #include @@ -283,11 +306,11 @@ static int RsaDecodeSignature(uint8_t** pInput, int inputSz) } #endif /* !NO_RSA_SIG_ENCODING */ -static void wolfBoot_verify_signature(uint8_t key_slot, +static void wolfBoot_verify_signature_rsa(uint8_t key_slot, struct wolfBoot_image *img, uint8_t *sig) { int ret; - uint8_t output[IMAGE_SIGNATURE_SIZE]; + uint8_t output[RSA_IMAGE_SIGNATURE_SIZE]; uint8_t* digest_out = NULL; uint8_t *pubkey = keystore_get_buffer(key_slot); int pubkey_sz = keystore_get_size(key_slot); @@ -303,10 +326,10 @@ static void wolfBoot_verify_signature(uint8_t key_slot, defined(WOLFBOOT_RENESAS_RSIP) ret = wc_InitRsaKey_ex(&rsa, NULL, RENESAS_DEVID); if (ret == 0) { - XMEMCPY(output, sig, IMAGE_SIGNATURE_SIZE); + XMEMCPY(output, sig, RSA_IMAGE_SIGNATURE_SIZE); RSA_VERIFY_FN(ret, wc_RsaSSL_Verify, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, - output, IMAGE_SIGNATURE_SIZE, &rsa); + output, RSA_IMAGE_SIGNATURE_SIZE, &rsa); /* The crypto callback success also verifies hash */ if (ret == 0) wolfBoot_image_confirm_signature_ok(img); @@ -319,9 +342,9 @@ static void wolfBoot_verify_signature(uint8_t key_slot, /* Import public key */ ret = wc_RsaPublicKeyDecode((byte*)pubkey, &inOutIdx, &rsa, pubkey_sz); if (ret >= 0) { - XMEMCPY(output, sig, IMAGE_SIGNATURE_SIZE); + XMEMCPY(output, sig, RSA_IMAGE_SIGNATURE_SIZE); RSA_VERIFY_FN(ret, - wc_RsaSSL_VerifyInline, output, IMAGE_SIGNATURE_SIZE, + wc_RsaSSL_VerifyInline, output, RSA_IMAGE_SIGNATURE_SIZE, &digest_out, &rsa); } } @@ -338,8 +361,10 @@ static void wolfBoot_verify_signature(uint8_t key_slot, RSA_VERIFY_HASH(img, digest_out); } } -#endif /* WOLFBOOT_SIGN_RSA2048 || WOLFBOOT_SIGN_3072 || \ - * WOLFBOOT_SIGN_RSA4096 */ + +#endif /* WOLFBOOT_SIGN_RSA2048 || WOLFBOOT_SIGN_RSA3072 || \ + * WOLFBOOT_SIGN_RSA4096 || WOLFBOOT_SIGN_SECONDARY_RSA2048 || + * WOLFBOOT_SIGN_SECONDARY_RSA3072 || WOLFBOOT_SIGN_SECONDARY_RSA4096 */ #ifdef WOLFBOOT_SIGN_LMS #include @@ -349,7 +374,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, #include #endif -static void wolfBoot_verify_signature(uint8_t key_slot, +static void wolfBoot_verify_signature_lms(uint8_t key_slot, struct wolfBoot_image *img, uint8_t *sig) { int ret = 0; @@ -393,7 +418,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, return; } - ret = wc_LmsKey_Verify(&lms, sig, IMAGE_SIGNATURE_SIZE, img->sha_hash, + ret = wc_LmsKey_Verify(&lms, sig, LMS_IMAGE_SIGNATURE_SIZE, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); if (ret == 0) { @@ -406,6 +431,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, wc_LmsKey_Free(&lms); } + #endif /* WOLFBOOT_SIGN_LMS */ #ifdef WOLFBOOT_SIGN_XMSS @@ -416,7 +442,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, #include #endif -static void wolfBoot_verify_signature(uint8_t key_slot, +static void wolfBoot_verify_signature_xmss(uint8_t key_slot, struct wolfBoot_image *img, uint8_t *sig) { int ret = 0; @@ -457,7 +483,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, return; } - ret = wc_XmssKey_Verify(&xmss, sig, IMAGE_SIGNATURE_SIZE, img->sha_hash, + ret = wc_XmssKey_Verify(&xmss, sig, XMSS_IMAGE_SIGNATURE_SIZE, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); if (ret == 0) { @@ -470,11 +496,12 @@ static void wolfBoot_verify_signature(uint8_t key_slot, wc_XmssKey_Free(&xmss); } + #endif /* WOLFBOOT_SIGN_XMSS */ #ifdef WOLFBOOT_SIGN_ML_DSA #include -static void wolfBoot_verify_signature(uint8_t key_slot, +static void wolfBoot_verify_signature_ml_dsa(uint8_t key_slot, struct wolfBoot_image *img, uint8_t *sig) { int ret = 0; @@ -532,9 +559,9 @@ static void wolfBoot_verify_signature(uint8_t key_slot, wolfBoot_printf("error: wc_MlDsaKey_GetPubLen returned %d\n", ret); ret = -1; } - else if (sig_len != IMAGE_SIGNATURE_SIZE) { + else if (sig_len != ML_DSA_IMAGE_SIGNATURE_SIZE) { wolfBoot_printf("error: ML-DSA sig len mismatch: got %d bytes " \ - "expected %d\n", sig_len, IMAGE_SIGNATURE_SIZE); + "expected %d\n", sig_len, ML_DSA_IMAGE_SIGNATURE_SIZE); ret = -1; } } @@ -554,7 +581,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, ML_DSA_LEVEL); /* Finally verify signagure. */ - ret = wc_MlDsaKey_Verify(&ml_dsa, sig, IMAGE_SIGNATURE_SIZE, + ret = wc_MlDsaKey_Verify(&ml_dsa, sig, ML_DSA_IMAGE_SIGNATURE_SIZE, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &verify_res); @@ -570,6 +597,7 @@ static void wolfBoot_verify_signature(uint8_t key_slot, wc_MlDsaKey_Free(&ml_dsa); } + #endif /* WOLFBOOT_SIGN_ML_DSA */ #endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY */ @@ -720,6 +748,7 @@ static int image_sha256(struct wolfBoot_image *img, uint8_t *hash) } while(position < img->fw_size); wc_Sha256Final(&sha256_ctx, hash); + wc_Sha256Free(&sha256_ctx); return 0; } @@ -737,12 +766,14 @@ static void key_sha256(uint8_t key_slot, uint8_t *hash) int pubkey_sz = keystore_get_size(key_slot); wc_Sha256 sha256_ctx; + memset(hash, 0, SHA256_DIGEST_SIZE); if (!pubkey || (pubkey_sz < 0)) return; wc_InitSha256(&sha256_ctx); wc_Sha256Update(&sha256_ctx, pubkey, (word32)pubkey_sz); wc_Sha256Final(&sha256_ctx, hash); + wc_Sha256Free(&sha256_ctx); } #endif /* WOLFBOOT_NO_SIGN */ #endif /* SHA2-256 */ @@ -796,6 +827,7 @@ static int image_sha384(struct wolfBoot_image *img, uint8_t *hash) } while(position < img->fw_size); wc_Sha384Final(&sha384_ctx, hash); + wc_Sha384Free(&sha384_ctx); return 0; } @@ -824,6 +856,7 @@ static void key_sha384(uint8_t key_slot, uint8_t *hash) wc_InitSha384(&sha384_ctx); wc_Sha384Update(&sha384_ctx, pubkey, (word32)pubkey_sz); wc_Sha384Final(&sha384_ctx, hash); + wc_Sha384Free(&sha384_ctx); } #endif /* WOLFBOOT_NO_SIGN */ #endif /* WOLFBOOT_HASH_SHA384 */ @@ -878,6 +911,7 @@ static int image_sha3_384(struct wolfBoot_image *img, uint8_t *hash) } while(position < img->fw_size); wc_Sha3_384_Final(&sha3_ctx, hash); + wc_Sha3_384_Free(&sha3_ctx); return 0; } #ifndef WOLFBOOT_NO_SIGN @@ -904,6 +938,7 @@ static void key_sha3_384(uint8_t key_slot, uint8_t *hash) wc_InitSha3_384(&sha3_ctx, NULL, INVALID_DEVID); wc_Sha3_384_Update(&sha3_ctx, pubkey, (word32)pubkey_sz); wc_Sha3_384_Final(&sha3_ctx, hash); + wc_Sha3_384_Free(&sha3_ctx); } #endif /* WOLFBOOT_NO_SIGN */ #endif /* SHA3-384 */ @@ -1168,8 +1203,6 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) int key_slot; stored_signature_size = get_header(img, HDR_SIGNATURE, &stored_signature); - if (stored_signature_size != IMAGE_SIGNATURE_SIZE) - return -1; pubkey_hint_size = get_header(img, HDR_PUBKEY, &pubkey_hint); if (pubkey_hint_size == WOLFBOOT_SHA_DIGEST_SIZE) { #if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \ @@ -1218,7 +1251,7 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) CONFIRM_MASK_VALID(image_part, key_mask); - /* wolfBoot_verify_signature() does not return the result directly. + /* wolfBoot_verify_signature_ecc() does not return the result directly. * A call to wolfBoot_image_confirm_signature_ok() is required in order to * confirm that the signature verification is OK. * @@ -1226,8 +1259,36 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) * img->signature_ok to 1. * */ - wolfBoot_verify_signature(key_slot, img, stored_signature); + wolfBoot_verify_signature_primary(key_slot, img, stored_signature); if (img->signature_ok == 1) +#ifdef SIGN_HYBRID + { + uint8_t *stored_secondary_signature; + uint16_t stored_secondary_signature_size; + /* Invalidate the signature_ok flag */ + wolfBoot_image_clear_signature_ok(img); + /* Load the pubkey hint for the secondary key */ + pubkey_hint_size = get_header(img, HDR_SECONDARY_PUBKEY, &pubkey_hint); + if (pubkey_hint_size == WOLFBOOT_SHA_DIGEST_SIZE) { + key_slot = keyslot_id_by_sha(pubkey_hint); + if (key_slot < 0) { + return -1; /* Key was not found */ + } + key_mask = keystore_get_mask(key_slot); + if (((1U << image_part) & key_mask) != (1U << image_part)) { + return -1; /* Key not allowed to verify this partition id */ + } + CONFIRM_MASK_VALID(image_part, key_mask); + stored_secondary_signature_size = get_header(img, + HDR_SECONDARY_SIGNATURE, &stored_secondary_signature); + wolfBoot_printf("Verification of hybrid signature\n"); + wolfBoot_verify_signature_secondary(key_slot, img, + stored_secondary_signature); + wolfBoot_printf("Done.\n"); + } + } + if (img->signature_ok == 1) +#endif return 0; return -2; } diff --git a/tools/config.mk b/tools/config.mk index 7f70024cd..288c10c17 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -106,5 +106,6 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO FLASH_OTP_KEYSTORE \ KEYVAULT_OBJ_SIZE \ KEYVAULT_MAX_ITEMS \ - NO_ARM_ASM + NO_ARM_ASM \ + SIGN_SECONDARY diff --git a/tools/keytools/keygen.c b/tools/keytools/keygen.c index aa78abc15..9b899f2a3 100644 --- a/tools/keytools/keygen.c +++ b/tools/keytools/keygen.c @@ -122,7 +122,7 @@ static int saveAsDer = 0; static WC_RNG rng; #ifndef KEYSLOT_MAX_PUBKEY_SIZE - #if defined(WOLFSSL_WC_DILITHIUM) + #if defined(KEYSTORE_PUBKEY_SIZE_ML_DSA) /* ML-DSA pub keys are big. */ #define KEYSLOT_MAX_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ML_DSA #else @@ -388,9 +388,11 @@ static uint32_t get_pubkey_size(uint32_t keyType) case KEYGEN_XMSS: size = KEYSTORE_PUBKEY_SIZE_XMSS; break; +#ifdef KEYSTORE_PUBKEY_SIZE_ML_DSA case KEYGEN_ML_DSA: size = KEYSTORE_PUBKEY_SIZE_ML_DSA; break; +#endif default: size = 0; } @@ -431,10 +433,14 @@ void keystore_add(uint32_t ktype, uint8_t *key, uint32_t sz, const char *keyfile #ifdef WOLFBOOT_UNIVERSAL_KEYSTORE slot_size = sizeof(struct keystore_slot); #else - slot_size = sizeof(struct keystore_slot) + sl.pubkey_size - + slot_size = sizeof(struct keystore_slot) + sl.pubkey_size - KEYSLOT_MAX_PUBKEY_SIZE; #endif fwrite(&sl, slot_size, 1, fpub_image); +#ifdef DEBUG_SIGNTOOL + printf("Added key to keystore: %s\n", keyfile); + WOLFSSL_BUFFER(key, sz); +#endif id_slot++; } @@ -1113,6 +1119,7 @@ int main(int argc, char** argv) #ifdef DEBUG_SIGNTOOL wolfSSL_Debugging_ON(); #endif + printf("Keystore size: %lu\n", (unsigned long)sizeof(struct keystore_slot)); /* Check arguments and print usage */ if (argc < 2) diff --git a/tools/keytools/sign.c b/tools/keytools/sign.c index cc119216a..00141f562 100644 --- a/tools/keytools/sign.c +++ b/tools/keytools/sign.c @@ -49,6 +49,14 @@ #include "wolfboot/version.h" +#ifdef DEBUG_SIGNTOOL +#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) +#define DEBUG_BUFFER(buf,sz) WOLFSSL_BUFFER(buf,sz) +#else +#define DEBUG_PRINT(...) do{}while(0) +#define DEBUG_BUFFER(buf,sz) do{}while(0) +#endif + #ifdef _WIN32 #include #define HAVE_MMAP 0 @@ -144,16 +152,19 @@ static inline int fp_truncate(FILE *f, size_t len) #define WOLFBOOT_MAGIC 0x464C4F57 /* WOLF */ -#define HDR_VERSION 0x01 -#define HDR_TIMESTAMP 0x02 -#define HDR_PUBKEY 0x10 -#define HDR_SIGNATURE 0x20 -#define HDR_POLICY_SIGNATURE 0x21 -#define HDR_IMG_TYPE 0x04 +#define HDR_VERSION 0x01 +#define HDR_TIMESTAMP 0x02 +#define HDR_SHA256 0x03 +#define HDR_IMG_TYPE 0x04 +#define HDR_PUBKEY 0x10 +#define HDR_SECONDARY_CIPHER 0x11 +#define HDR_SECONDARY_PUBKEY 0x12 +#define HDR_SHA3_384 0x13 +#define HDR_SHA384 0x14 +#define HDR_SIGNATURE 0x20 +#define HDR_POLICY_SIGNATURE 0x21 +#define HDR_SECONDARY_SIGNATURE 0x22 -#define HDR_SHA256 0x03 -#define HDR_SHA3_384 0x13 -#define HDR_SHA384 0x14 #define HDR_SHA256_LEN 32 #define HDR_SHA384_LEN 48 @@ -173,6 +184,7 @@ static inline int fp_truncate(FILE *f, size_t len) #define HDR_IMG_TYPE_WOLFBOOT 0x0000 #define HDR_IMG_TYPE_APP 0x0001 #define HDR_IMG_TYPE_DIFF 0x00D0 +#define HDR_IMG_TYPE_HYBRID 0x0080 #define HASH_SHA256 HDR_SHA256 #define HASH_SHA384 HDR_SHA384 @@ -232,7 +244,7 @@ static void header_append_tag(uint8_t* header, uint32_t* idx, uint16_t tag, /* Globals */ static const char wolfboot_delta_file[] = "/tmp/wolfboot-delta.bin"; -static union { +static struct { #ifdef HAVE_ED25519 ed25519_key ed; #endif @@ -264,11 +276,14 @@ struct cmd_options { int encrypt; int hash_algo; int sign; + int hybrid; + int secondary_sign; int delta; int no_ts; int sign_wenc; const char *image_file; const char *key_file; + const char *secondary_key_file; const char *fw_version; const char *signature_file; const char *policy_file; @@ -280,6 +295,7 @@ struct cmd_options { uint32_t pubkey_sz; uint32_t header_sz; uint32_t signature_sz; + uint32_t secondary_signature_sz; uint32_t policy_sz; uint8_t partition_id; uint32_t custom_tlvs; @@ -296,15 +312,14 @@ static struct cmd_options CMD = { .encrypt = ENC_OFF, .hash_algo = HASH_SHA256, .header_sz = IMAGE_HEADER_SIZE, - .partition_id = HDR_IMG_TYPE_APP - + .partition_id = HDR_IMG_TYPE_APP, + .hybrid = 0 }; - static int load_key_ecc(int sign_type, uint32_t curve_sz, int curve_id, int header_sz, uint8_t **key_buffer, uint32_t *key_buffer_sz, - uint8_t **pubkey, uint32_t *pubkey_sz) + uint8_t **pubkey, uint32_t *pubkey_sz, int secondary) { int ret = -1; int initRet = -1; @@ -314,9 +329,7 @@ static int load_key_ecc(int sign_type, uint32_t curve_sz, int curve_id, *pubkey_sz = curve_sz * 2; *pubkey = malloc(*pubkey_sz); /* assume malloc works */ - initRet = ret = wc_ecc_init(&key.ecc); - if (CMD.manual_sign || CMD.sha_only) { /* raw (public x + public y) */ if (*key_buffer_sz == (curve_sz * 2)) { @@ -389,9 +402,15 @@ static int load_key_ecc(int sign_type, uint32_t curve_sz, int curve_id, free(*pubkey); if (ret == 0 || CMD.sign != SIGN_AUTO) { - CMD.sign = sign_type; CMD.header_sz = header_sz; - CMD.signature_sz = (curve_sz * 2); + if (secondary) { + CMD.secondary_sign = sign_type; + CMD.secondary_signature_sz = (curve_sz * 2); + printf("Secondary ECC key, size: %d\n", CMD.secondary_signature_sz); + } else { + CMD.sign = sign_type; + CMD.signature_sz = (curve_sz * 2); + } ret = 0; } return ret; @@ -400,7 +419,7 @@ static int load_key_ecc(int sign_type, uint32_t curve_sz, int curve_id, static int load_key_rsa(int sign_type, uint32_t rsa_keysz, uint32_t rsa_pubkeysz, int header_sz, uint8_t **key_buffer, uint32_t *key_buffer_sz, - uint8_t **pubkey, uint32_t *pubkey_sz) + uint8_t **pubkey, uint32_t *pubkey_sz, int secondary) { int ret = -1; int initRet = -1; @@ -413,7 +432,6 @@ static int load_key_rsa(int sign_type, uint32_t rsa_keysz, uint32_t rsa_pubkeysz *pubkey_sz = *key_buffer_sz; if (*pubkey_sz <= rsa_pubkeysz) { - CMD.sign = sign_type; CMD.header_sz = header_sz; if (CMD.policy_sign) { CMD.header_sz += 512; @@ -421,7 +439,13 @@ static int load_key_rsa(int sign_type, uint32_t rsa_keysz, uint32_t rsa_pubkeysz else if (sign_type == SIGN_RSA3072 && CMD.hash_algo != HASH_SHA256) { CMD.header_sz += 512; } - CMD.signature_sz = rsa_keysz; + if (secondary) { + CMD.secondary_signature_sz = rsa_keysz; + CMD.secondary_sign = sign_type; + } else { + CMD.sign = sign_type; + CMD.signature_sz = rsa_keysz; + } } ret = 0; } @@ -452,7 +476,6 @@ static int load_key_rsa(int sign_type, uint32_t rsa_keysz, uint32_t rsa_pubkeysz } if (ret == 0 || CMD.sign != SIGN_AUTO) { - CMD.sign = sign_type; CMD.header_sz = header_sz; if (CMD.policy_sign) { CMD.header_sz += 512; @@ -460,7 +483,13 @@ static int load_key_rsa(int sign_type, uint32_t rsa_keysz, uint32_t rsa_pubkeysz else if (sign_type == SIGN_RSA3072 && CMD.hash_algo != HASH_SHA256) { CMD.header_sz += 512; } - CMD.signature_sz = keySzOut; + if (secondary) { + CMD.secondary_sign = sign_type; + CMD.secondary_signature_sz = keySzOut; + } else { + CMD.sign = sign_type; + CMD.signature_sz = keySzOut; + } printf("Found RSA%d key\n", keySzOut); } } @@ -468,7 +497,7 @@ static int load_key_rsa(int sign_type, uint32_t rsa_keysz, uint32_t rsa_pubkeysz } static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, - uint8_t **pubkey, uint32_t *pubkey_sz) + uint8_t **pubkey, uint32_t *pubkey_sz, int secondary) { int ret = -1; int initRet = -1; @@ -482,12 +511,19 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, int priv_sz = 0; int pub_sz = 0; #endif + int sign = CMD.sign; + const char *key_file = CMD.key_file; /* open and load key buffer */ *key_buffer = NULL; - f = fopen(CMD.key_file, "rb"); + if (secondary) { + key_file = CMD.secondary_key_file; + sign = CMD.secondary_sign; + } + + f = fopen(key_file, "rb"); if (f == NULL) { - printf("Open key file %s failed\n", CMD.key_file); + printf("Open key file %s failed\n", key_file); goto failure; } fseek(f, 0, SEEK_END); @@ -506,8 +542,9 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, printf("Key buffer malloc error!\n"); goto failure; } + DEBUG_PRINT("Key buffer size: %d\n", *key_buffer_sz); - switch (CMD.sign) { + switch (sign) { /* auto, just try them all, no harm no foul */ default: FALL_THROUGH; @@ -561,10 +598,14 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, free(*pubkey); /* break if we succeed or are not using auto */ - if (ret == 0 || CMD.sign != SIGN_AUTO) { - CMD.header_sz = 256; - CMD.signature_sz = 64; - CMD.sign = SIGN_ED25519; + if (ret == 0 || sign != SIGN_AUTO) { + if (CMD.header_sz < 256) + CMD.header_sz = 256; + if (secondary) + CMD.secondary_signature_sz = 64; + else + CMD.signature_sz = 64; + sign = SIGN_ED25519; printf("Found ED25519 key\n"); break; } @@ -620,10 +661,14 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, free(*pubkey); /* break if we succeed or are not using auto */ - if (ret == 0 || CMD.sign != SIGN_AUTO) { - CMD.header_sz = 512; - CMD.signature_sz = 114; - CMD.sign = SIGN_ED448; + if (ret == 0 || sign != SIGN_AUTO) { + if (CMD.header_sz < 512) + CMD.header_sz = 512; + if (secondary) + CMD.secondary_signature_sz = 114; + else + CMD.signature_sz = 114; + sign = SIGN_ED448; printf("Found ED448 key\n"); break; } @@ -631,38 +676,38 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, case SIGN_ECC256: ret = load_key_ecc(SIGN_ECC256, 32, ECC_SECP256R1, 256, - key_buffer, key_buffer_sz, pubkey, pubkey_sz); + key_buffer, key_buffer_sz, pubkey, pubkey_sz, secondary); if (ret == 0) break; FALL_THROUGH; case SIGN_ECC384: ret = load_key_ecc(SIGN_ECC384, 48, ECC_SECP384R1, 512, - key_buffer, key_buffer_sz, pubkey, pubkey_sz); + key_buffer, key_buffer_sz, pubkey, pubkey_sz, secondary); if (ret == 0) break; FALL_THROUGH; case SIGN_ECC521: ret = load_key_ecc(SIGN_ECC521, 66, ECC_SECP521R1, 512, - key_buffer, key_buffer_sz, pubkey, pubkey_sz); + key_buffer, key_buffer_sz, pubkey, pubkey_sz, secondary); if (ret == 0) break; FALL_THROUGH; /* we didn't solve the key, keep trying */ case SIGN_RSA2048: ret = load_key_rsa(SIGN_RSA2048, 256, KEYSTORE_PUBKEY_SIZE_RSA2048, 512, - key_buffer, key_buffer_sz, pubkey, pubkey_sz); + key_buffer, key_buffer_sz, pubkey, pubkey_sz, secondary); if (ret == 0) break; FALL_THROUGH; /* we didn't solve the key, keep trying */ case SIGN_RSA3072: ret = load_key_rsa(SIGN_RSA3072, 384, KEYSTORE_PUBKEY_SIZE_RSA3072, 512, - key_buffer, key_buffer_sz, pubkey, pubkey_sz); + key_buffer, key_buffer_sz, pubkey, pubkey_sz, secondary); if (ret == 0) break; FALL_THROUGH; /* we didn't solve the key, keep trying */ case SIGN_RSA4096: ret = load_key_rsa(SIGN_RSA4096, 512, KEYSTORE_PUBKEY_SIZE_RSA4096, 1024, - key_buffer, key_buffer_sz, pubkey, pubkey_sz); + key_buffer, key_buffer_sz, pubkey, pubkey_sz, secondary); if (ret == 0) break; @@ -671,7 +716,7 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, case SIGN_LMS: ret = -1; - if (CMD.sign == SIGN_AUTO) { + if (sign == SIGN_AUTO) { /* LMS is stateful and requires additional config, and is not * compatible with SIGN_AUTO. */ printf("error: SIGN_AUTO with LMS is not supported\n"); @@ -713,7 +758,7 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, case SIGN_XMSS: ret = -1; - if (CMD.sign == SIGN_AUTO) { + if (sign == SIGN_AUTO) { /* XMSS is stateful and requires additional config, and is not * compatible with SIGN_AUTO. */ printf("error: SIGN_AUTO with XMSS is not supported\n"); @@ -732,8 +777,8 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, break; } - printf("info: xmss sk len: %d\n", priv_sz); - printf("info: xmss pk len: %d\n", KEYSTORE_PUBKEY_SIZE_XMSS); + DEBUG_PRINT("info: xmss sk len: %d\n", priv_sz); + DEBUG_PRINT("info: xmss pk len: %d\n", KEYSTORE_PUBKEY_SIZE_XMSS); if (*key_buffer_sz == (priv_sz + KEYSTORE_PUBKEY_SIZE_XMSS)) { /* priv + pub */ @@ -786,8 +831,8 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, priv_sz -= pub_sz; } - printf("info: ml-dsa priv len: %d\n", priv_sz); - printf("info: ml-dsa pub len: %d\n", pub_sz); + DEBUG_PRINT("info: ml-dsa priv len: %d\n", priv_sz); + DEBUG_PRINT("info: ml-dsa pub len: %d\n", pub_sz); if ((int)*key_buffer_sz == (priv_sz + pub_sz)) { /* priv + pub */ @@ -816,7 +861,7 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, #endif /* WOLFSSL_WC_DILITHIUM */ break; - } /* end switch (CMD.sign) */ + } /* end switch (sign) */ if (ret != 0) { printf("Key decode error %d\n", ret); @@ -831,10 +876,8 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, printf("image header size calculated at runtime (%u bytes)\n", CMD.header_sz); } -#ifdef DEBUG_SIGNTOOL - printf("Pubkey %d\n", *pubkey_sz); - WOLFSSL_BUFFER(*pubkey, *pubkey_sz); -#endif + DEBUG_PRINT("Pubkey %d\n", *pubkey_sz); + DEBUG_BUFFER(*pubkey, *pubkey_sz); return *key_buffer; failure: @@ -848,10 +891,12 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, /* Sign the digest */ static int sign_digest(int sign, int hash_algo, uint8_t* signature, uint32_t* signature_sz, - uint8_t* digest, uint32_t digest_sz) + uint8_t* digest, uint32_t digest_sz, int secondary) { int ret; WC_RNG rng; + printf("Sign: %02x\n", sign >> 8); + (void)secondary; if ((ret = wc_InitRng(&rng)) != 0) { return ret; @@ -934,13 +979,17 @@ static int sign_digest(int sign, int hash_algo, #endif #ifdef WOLFSSL_HAVE_LMS if (sign == SIGN_LMS) { + const char *key_file = CMD.key_file; + if (secondary) { + key_file = CMD.secondary_key_file; + } /* Set the callbacks, so LMS can update the private key while signing */ ret = wc_LmsKey_SetWriteCb(&key.lms, lms_write_key); if (ret == 0) { ret = wc_LmsKey_SetReadCb(&key.lms, lms_read_key); } if (ret == 0) { - ret = wc_LmsKey_SetContext(&key.lms, (void*)CMD.key_file); + ret = wc_LmsKey_SetContext(&key.lms, (void*)key_file); } if (ret == 0) { ret = wc_LmsKey_Reload(&key.lms); @@ -957,6 +1006,10 @@ static int sign_digest(int sign, int hash_algo, #endif /* WOLFSSL_HAVE_LMS */ #ifdef WOLFSSL_HAVE_XMSS if (sign == SIGN_XMSS) { + const char *key_file = CMD.key_file; + if (secondary) { + key_file = CMD.secondary_key_file; + } ret = wc_XmssKey_Init(&key.xmss, NULL, INVALID_DEVID); /* Set the callbacks, so XMSS can update the private key while signing */ if (ret == 0) { @@ -966,7 +1019,7 @@ static int sign_digest(int sign, int hash_algo, ret = wc_XmssKey_SetReadCb(&key.xmss, xmss_read_key); } if (ret == 0) { - ret = wc_XmssKey_SetContext(&key.xmss, (void*)CMD.key_file); + ret = wc_XmssKey_SetContext(&key.xmss, (void*)key_file); } if (ret == 0) { ret = wc_XmssKey_SetParamStr(&key.xmss, WOLFBOOT_XMSS_PARAMS); @@ -992,7 +1045,7 @@ static int sign_digest(int sign, int hash_algo, digest, digest_sz, &rng); } if (ret != 0) { - fprintf(stderr, "error signing with XMSS: %d\n", ret); + fprintf(stderr, "error signing with ML-DSA: %d\n", ret); } } else @@ -1004,10 +1057,13 @@ static int sign_digest(int sign, int hash_algo, return ret; } +#define ALIGN_8(x) while ((x % 8) != 4) { x++; } +#define ALIGN_4(x) while ((x % 4) != 0) { x++; } + static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, const char *image_file, const char *outfile, uint32_t delta_base_version, uint32_t patch_len, uint32_t patch_inv_off, - uint32_t patch_inv_len) + uint32_t patch_inv_len, const uint8_t *secondary_key, uint32_t secondary_key_sz) { uint32_t header_idx; uint8_t *header; @@ -1016,9 +1072,11 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, struct stat attrib; uint16_t image_type; uint8_t* signature = NULL; + uint8_t* secondary_signature = NULL; uint8_t* policy = NULL; int ret = -1; - uint8_t buf[1024]; + uint8_t buf[4096]; + uint8_t second_buf[4096]; uint32_t read_sz, pos; uint8_t digest[48]; /* max digest */ uint32_t digest_sz = 0; @@ -1057,8 +1115,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, &fw_version32); /* Append pad bytes, so timestamp val field is 8-byte aligned */ - while ((header_idx % 8) != 4) - header_idx++; + ALIGN_8(header_idx); if (!CMD.no_ts) { /* Append Timestamp field */ @@ -1077,8 +1134,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, if (is_diff) { /* Append pad bytes, so fields are 4-byte aligned */ - while ((header_idx % 4) != 0) - header_idx++; + ALIGN_4(header_idx); header_append_tag(header, &header_idx, HDR_IMG_DELTA_BASE, 4, &delta_base_version); header_append_tag(header, &header_idx, HDR_IMG_DELTA_SIZE, 4, @@ -1101,8 +1157,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, /* The offset '4' takes into account 2B Tag + 2B Len, so that the * Value starts at (addr % 8 == 0) position. */ - while ((header_idx % 8) != 4) - header_idx++; + ALIGN_8(header_idx); if (CMD.custom_tlv[i].buffer == NULL) { header_append_tag(header, &header_idx, CMD.custom_tlv[i].tag, @@ -1118,17 +1173,53 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, /* The offset '4' takes into account 2B Tag + 2B Len, so that the Value * starts at (addr % 8 == 0) position. */ - while ((header_idx % 8) != 4) - header_idx++; + ALIGN_8(header_idx); /* Calculate hashes */ if (CMD.hash_algo == HASH_SHA256) { #ifndef NO_SHA256 wc_Sha256 sha; - printf("Calculating SHA256 digest...\n"); + digest_sz = SHA256_DIGEST_SIZE; + /* pubkey hash calculation */ ret = wc_InitSha256_ex(&sha, NULL, INVALID_DEVID); if (ret == 0) { + printf("Hashing primary pubkey, size: %d\n", pubkey_sz); + ret = wc_Sha256Update(&sha, pubkey, pubkey_sz); + if (ret == 0) + wc_Sha256Final(&sha, buf); + wc_Sha256Free(&sha); + /* Add Pubkey Hash to header */ + header_append_tag(header, &header_idx, HDR_PUBKEY, digest_sz, buf); + DEBUG_PRINT("Pubkey hash %d\n", digest_sz); + DEBUG_BUFFER(buf, digest_sz); + ALIGN_8(header_idx); + } + /* secondary public key in hybrid mode */ + if (ret == 0 && CMD.hybrid && secondary_key_sz > 0) { + ret = wc_InitSha256_ex(&sha, NULL, INVALID_DEVID); + DEBUG_PRINT("Hashing secondary pubkey, size: %d\n", secondary_key_sz); + if (ret == 0) { + ret = wc_Sha256Update(&sha, secondary_key, secondary_key_sz); + if (ret == 0) + wc_Sha256Final(&sha, second_buf); + wc_Sha256Free(&sha); + /* Add Secondary cipher to header */ + header_append_tag(header, &header_idx, HDR_SECONDARY_CIPHER, 2, &CMD.secondary_sign); + ALIGN_8(header_idx); + /* Add Secondary Pubkey Hash to header */ + header_append_tag(header, &header_idx, HDR_SECONDARY_PUBKEY, digest_sz, second_buf); + DEBUG_PRINT("Secondary pubkey hash %d\n", digest_sz); + DEBUG_BUFFER(second_buf, digest_sz); + } + } + if (ret == 0) { + printf("Calculating SHA256 digest...\n"); + ALIGN_8(header_idx); + ret = wc_InitSha256_ex(&sha, NULL, INVALID_DEVID); + } + if (ret == 0) { + ALIGN_8(header_idx); /* Hash Header */ ret = wc_Sha256Update(&sha, header, header_idx); @@ -1148,30 +1239,55 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, pos += read_sz; } fclose(f); - if (ret == 0) - wc_Sha256Final(&sha, digest); - wc_Sha256Free(&sha); - } - /* pubkey hash calculation */ - if (ret == 0) { - ret = wc_InitSha256_ex(&sha, NULL, INVALID_DEVID); if (ret == 0) { - ret = wc_Sha256Update(&sha, pubkey, pubkey_sz); - if (ret == 0) - wc_Sha256Final(&sha, buf); - wc_Sha256Free(&sha); + wc_Sha256Final(&sha, digest); + digest_sz = HDR_SHA256_LEN; } + wc_Sha256Free(&sha); } - if (ret == 0) - digest_sz = HDR_SHA256_LEN; #endif } else if (CMD.hash_algo == HASH_SHA384) { #ifndef NO_SHA384 wc_Sha384 sha; + digest_sz = SHA384_DIGEST_SIZE; + ALIGN_8(header_idx); printf("Calculating SHA384 digest...\n"); + /* pubkey hash calculation */ ret = wc_InitSha384_ex(&sha, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha384Update(&sha, pubkey, pubkey_sz); + if (ret == 0) { + wc_Sha384Final(&sha, buf); + /* Add Pubkey Hash to header */ + ALIGN_8(header_idx); + header_append_tag(header, &header_idx, HDR_PUBKEY, digest_sz, buf); + DEBUG_PRINT("Pubkey hash %d\n", digest_sz); + DEBUG_BUFFER(buf, digest_sz); + ALIGN_8(header_idx); + } + wc_Sha384Free(&sha); + } + if (ret == 0 && CMD.hybrid && secondary_key_sz > 0) { + ret = wc_InitSha384_ex(&sha, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha384Update(&sha, secondary_key, secondary_key_sz); + if (ret == 0) { + wc_Sha384Final(&sha, second_buf); + /* Add Secondary cipher to header */ + header_append_tag(header, &header_idx, HDR_SECONDARY_CIPHER, 2, &CMD.secondary_sign); + /* Add Secondary Pubkey Hash to header */ + header_append_tag(header, &header_idx, HDR_SECONDARY_PUBKEY, digest_sz, second_buf); + DEBUG_PRINT("Secondary pubkey hash %d\n", digest_sz); + DEBUG_BUFFER(second_buf, digest_sz); + ALIGN_8(header_idx); + } + wc_Sha384Free(&sha); + } + } + if (ret == 0) + ret = wc_InitSha384_ex(&sha, NULL, INVALID_DEVID); if (ret == 0) { /* Hash Header */ ret = wc_Sha384Update(&sha, header, header_idx); @@ -1192,32 +1308,53 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, pos += read_sz; } fclose(f); - if (ret == 0) - wc_Sha384Final(&sha, digest); - wc_Sha384Free(&sha); - } - /* pubkey hash calculation */ - if (ret == 0) { - ret = wc_InitSha384_ex(&sha, NULL, INVALID_DEVID); if (ret == 0) { - ret = wc_Sha384Update(&sha, pubkey, pubkey_sz); - if (ret == 0) - wc_Sha384Final(&sha, buf); - wc_Sha384Free(&sha); + wc_Sha384Final(&sha, digest); + digest_sz = HDR_SHA384_LEN; } + wc_Sha384Free(&sha); } - if (ret == 0) - digest_sz = HDR_SHA384_LEN; #endif } else if (CMD.hash_algo == HASH_SHA3) { #ifdef WOLFSSL_SHA3 wc_Sha3 sha; - - printf("Calculating SHA3 digest...\n"); - + digest_sz = HDR_SHA3_384_LEN; ret = wc_InitSha3_384(&sha, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha3_384_Update(&sha, pubkey, pubkey_sz); + if (ret == 0) { + ret = wc_Sha3_384_Final(&sha, buf); + header_append_tag(header, &header_idx, HDR_PUBKEY, digest_sz, buf); + DEBUG_PRINT("Pubkey hash %d\n", digest_sz); + DEBUG_BUFFER(buf, digest_sz); + ALIGN_8(header_idx); + } + wc_Sha3_384_Free(&sha); + } + if (ret == 0 && CMD.hybrid && secondary_key_sz > 0) { + ALIGN_8(header_idx); + ret = wc_InitSha3_384(&sha, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha3_384_Update(&sha, secondary_key, secondary_key_sz); + if (ret == 0) { + ret = wc_Sha3_384_Final(&sha, second_buf); + /* Add Secondary cipher to header */ + header_append_tag(header, &header_idx, HDR_SECONDARY_CIPHER, 2, &CMD.secondary_sign); + header_append_tag(header, &header_idx, HDR_SECONDARY_PUBKEY, digest_sz, second_buf); + DEBUG_PRINT("Secondary pubkey hash %d\n", digest_sz); + DEBUG_BUFFER(second_buf, digest_sz); + ALIGN_8(header_idx); + } + wc_Sha3_384_Free(&sha); + } + } + if (ret == 0) { + printf("Calculating SHA3 digest...\n"); + ALIGN_8(header_idx); + ret = wc_InitSha3_384(&sha, NULL, INVALID_DEVID); + } if (ret == 0) { /* Hash Header */ ret = wc_Sha3_384_Update(&sha, header, header_idx); @@ -1238,42 +1375,25 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, pos += read_sz; } fclose(f); - if (ret == 0) + if (ret == 0) { ret = wc_Sha3_384_Final(&sha, digest); + digest_sz = HDR_SHA3_384_LEN; + } wc_Sha3_384_Free(&sha); } - /* pubkey hash calculation */ - if (ret == 0) { - ret = wc_InitSha3_384(&sha, NULL, INVALID_DEVID); - if (ret == 0) { - ret = wc_Sha3_384_Update(&sha, pubkey, pubkey_sz); - if (ret == 0) - ret = wc_Sha3_384_Final(&sha, buf); - wc_Sha3_384_Free(&sha); - } - } - if (ret == 0) - digest_sz = HDR_SHA3_384_LEN; #endif } if (digest_sz == 0) { printf("Hash algorithm error %d\n", ret); goto failure; } -#ifdef DEBUG_SIGNTOOL - printf("Image hash %d\n", digest_sz); - WOLFSSL_BUFFER(digest, digest_sz); - printf("Pubkey hash %d\n", digest_sz); - WOLFSSL_BUFFER(buf, digest_sz); -#endif + DEBUG_PRINT("Image hash %d\n", digest_sz); + DEBUG_BUFFER(digest, digest_sz); /* Add image hash to header */ header_append_tag(header, &header_idx, CMD.hash_algo, digest_sz, digest); if (CMD.sign != NO_SIGN) { - /* Add Pubkey Hash to header */ - header_append_tag(header, &header_idx, HDR_PUBKEY, digest_sz, buf); - /* If hash only, then save digest and exit */ if (CMD.sha_only) { f = fopen(outfile, "wb"); @@ -1295,25 +1415,23 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, printf("Signature malloc error!\n"); goto failure; } - memset(signature, 0, CMD.signature_sz); + memset(signature, 0, CMD.signature_sz); + DEBUG_PRINT("Signature sz (malloc): %d\n", CMD.signature_sz); if (!CMD.manual_sign) { printf("Signing the digest...\n"); -#ifdef DEBUG_SIGNTOOL - printf("Digest %d\n", digest_sz); - WOLFSSL_BUFFER(digest, digest_sz); -#endif - + DEBUG_PRINT("Digest %d\n", digest_sz); + DEBUG_BUFFER(digest, digest_sz); /* Sign the digest */ ret = sign_digest(CMD.sign, CMD.hash_algo, - signature, &CMD.signature_sz, digest, digest_sz); + signature, &CMD.signature_sz, digest, digest_sz, 0); if (ret != 0) { printf("Signing error %d\n", ret); goto failure; } } else { - printf("Opening signature file %s\n", CMD.signature_file); + DEBUG_PRINT("Opening signature file %s\n", CMD.signature_file); f = fopen(CMD.signature_file, "rb"); if (f == NULL) { @@ -1329,6 +1447,22 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, CMD.signature_sz = io_sz; } + if (CMD.hybrid) { + /* Sign the digest again with the secondary key */ + secondary_signature = malloc(CMD.secondary_signature_sz); + if (secondary_signature == NULL) { + printf("Secondary Signature malloc error!\n"); + goto failure; + } + memset(secondary_signature, 0, CMD.secondary_signature_sz); + ret = sign_digest(CMD.secondary_sign, CMD.hash_algo, + secondary_signature, &CMD.secondary_signature_sz, digest, digest_sz, 1); + if (ret != 0) { + printf("Secondary Signing error %d\n", ret); + goto failure; + } + } + /* Signing Policy */ if (CMD.policy_sign) { /* Policy is always SHA2-256 */ @@ -1366,15 +1500,13 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, } printf("Signing the policy digest...\n"); -#ifdef DEBUG_SIGNTOOL - printf("Policy Digest %d\n", digest_sz); - WOLFSSL_BUFFER(digest, digest_sz); -#endif + DEBUG_PRINT("Policy Digest %d\n", digest_sz); + DEBUG_BUFFER(digest, digest_sz); /* Policy is always SHA2-256 */ ret = sign_digest(CMD.sign, HASH_SHA256, policy + sizeof(uint32_t), &CMD.policy_sz, - digest, digest_sz); + digest, digest_sz, 0); if (ret != 0) { printf("Signing policy error %d\n", ret); goto failure; @@ -1401,21 +1533,28 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, } } -#ifdef DEBUG_SIGNTOOL - printf("Signature %d\n", CMD.signature_sz); - WOLFSSL_BUFFER(signature, CMD.signature_sz); + DEBUG_PRINT("Signature %d\n", CMD.signature_sz); + DEBUG_BUFFER(signature, CMD.signature_sz); if (CMD.policy_sign) { - printf("PCR Mask 0x%08x\n", *((uint32_t*)policy)); - printf("Policy Signature %d\n", CMD.policy_sz); - WOLFSSL_BUFFER(policy + sizeof(uint32_t), CMD.policy_sz); + DEBUG_PRINT("PCR Mask 0x%08x\n", *((uint32_t*)policy)); + DEBUG_PRINT("Policy Signature %d\n", CMD.policy_sz); + DEBUG_BUFFER(policy + sizeof(uint32_t), CMD.policy_sz); } -#endif /* Add signature to header */ + ALIGN_8(header_idx); header_append_tag(header, &header_idx, HDR_SIGNATURE, CMD.signature_sz, signature); + if (CMD.hybrid) { + /* Add secondary signature to header */ + ALIGN_8(header_idx); + header_append_tag(header, &header_idx, HDR_SECONDARY_SIGNATURE, + CMD.secondary_signature_sz, secondary_signature); + } + if (CMD.policy_sign) { + ALIGN_8(header_idx); /* Add policy signature to header */ header_append_tag(header, &header_idx, HDR_POLICY_SIGNATURE, CMD.policy_sz + (uint16_t)sizeof(uint32_t), policy); @@ -1550,7 +1689,8 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, static int make_header(uint8_t *pubkey, uint32_t pubkey_sz, const char *image_file, const char *outfile) { - return make_header_ex(0, pubkey, pubkey_sz, image_file, outfile, 0, 0, 0, 0); + return make_header_ex(0, pubkey, pubkey_sz, image_file, outfile, 0, 0, 0, 0, + NULL, 0); } static int make_header_delta(uint8_t *pubkey, uint32_t pubkey_sz, @@ -1560,7 +1700,16 @@ static int make_header_delta(uint8_t *pubkey, uint32_t pubkey_sz, { return make_header_ex(1, pubkey, pubkey_sz, image_file, outfile, delta_base_version, patch_len, - patch_inv_off, patch_inv_len); + patch_inv_off, patch_inv_len, + NULL, 0); +} + +static int make_hybrid_header(uint8_t *pubkey, uint32_t pubkey_sz, + const char *image_file, const char *outfile, + const uint8_t *secondary_key, uint32_t secondary_key_sz) +{ + return make_header_ex(0, pubkey, pubkey_sz, image_file, outfile, 0, 0, 0, 0, + secondary_key, secondary_key_sz); } static int base_diff(const char *f_base, uint8_t *pubkey, uint32_t pubkey_sz, int padding) @@ -1864,6 +2013,161 @@ uint64_t arg2num(const char *arg, size_t len) return ret; } +static void set_signature_sizes(int secondary) +{ + uint32_t *sz = &CMD.signature_sz; + int *sign = &CMD.sign; + if (secondary) { + sz = &CMD.secondary_signature_sz; + sign = &CMD.secondary_sign; + } + /* get header and signature sizes */ + if (*sign == SIGN_ED25519) { + if (CMD.header_sz < 256) + CMD.header_sz = 256; + *sz = 64; + } + else if (*sign == SIGN_ED448) { + if (CMD.header_sz < 512) + CMD.header_sz = 512; + *sz = 114; + } + else if (*sign == SIGN_ECC256) { + if (CMD.header_sz < 256) + CMD.header_sz = 256; + *sz = 64; + } + else if (*sign == SIGN_ECC384) { + if (CMD.header_sz < 512) + CMD.header_sz = 512; + *sz = 96; + } + else if (*sign == SIGN_ECC521) { + if (CMD.header_sz < 512) + CMD.header_sz = 512; + *sz = 132; + } + else if (*sign == SIGN_RSA2048) { + if (CMD.header_sz < 512) + CMD.header_sz = 512; + *sz = 256; + } + else if (*sign == SIGN_RSA3072) { + if ((CMD.header_sz < 1024) && (CMD.hash_algo != HASH_SHA256)) + CMD.header_sz = 1024; + if (CMD.header_sz < 512) + CMD.header_sz = 512; + *sz = 384; + } + else if (*sign == SIGN_RSA4096) { + if (CMD.header_sz < 1024) + CMD.header_sz = 1024; + *sz = 512; + } +#ifdef WOLFSSL_HAVE_LMS + else if (*sign == SIGN_LMS) { + int lms_ret = 0; + word32 sig_sz = 0; + + lms_ret = wc_LmsKey_Init(&key.lms, NULL, INVALID_DEVID); + if (lms_ret != 0) { + fprintf(stderr, "error: wc_LmsKey_Init returned %d\n", lms_ret); + exit(1); + } + + lms_ret = wc_LmsKey_SetParameters(&key.lms, LMS_LEVELS, + LMS_HEIGHT, LMS_WINTERNITZ); + if (lms_ret != 0) { + fprintf(stderr, "error: wc_LmsKey_SetParameters(%d, %d, %d)" \ + " returned %d\n", LMS_LEVELS, LMS_HEIGHT, + LMS_WINTERNITZ, lms_ret); + exit(1); + } + + printf("info: using LMS parameters: L%d-H%d-W%d\n", LMS_LEVELS, + LMS_HEIGHT, LMS_WINTERNITZ); + + lms_ret = wc_LmsKey_GetSigLen(&key.lms, &sig_sz); + if (lms_ret != 0) { + fprintf(stderr, "error: wc_LmsKey_GetSigLen returned %d\n", + lms_ret); + exit(1); + } + + DEBUG_PRINT("info: LMS signature size: %d\n", sig_sz); + + CMD.header_sz = 2 * sig_sz; + *sz = sig_sz; + } +#endif /* WOLFSSL_HAVE_LMS */ +#ifdef WOLFSSL_HAVE_XMSS + else if (*sign == SIGN_XMSS) { + int xmss_ret = 0; + word32 sig_sz = 0; + + xmss_ret = wc_XmssKey_Init(&key.xmss, NULL, INVALID_DEVID); + if (xmss_ret != 0) { + fprintf(stderr, "error: wc_XmssKey_Init returned %d\n", xmss_ret); + exit(1); + } + + xmss_ret = wc_XmssKey_SetParamStr(&key.xmss, WOLFBOOT_XMSS_PARAMS); + if (xmss_ret != 0) { + fprintf(stderr, "error: wc_XmssKey_SetParamStr(%s)" \ + " returned %d\n", WOLFBOOT_XMSS_PARAMS, xmss_ret); + exit(1); + } + + printf("info: using XMSS parameters: %s\n", WOLFBOOT_XMSS_PARAMS); + + xmss_ret = wc_XmssKey_GetSigLen(&key.xmss, &sig_sz); + if (xmss_ret != 0) { + fprintf(stderr, "error: wc_XmssKey_GetSigLen returned %d\n", + xmss_ret); + exit(1); + } + + DEBUG_PRINT("info: XMSS signature size: %d\n", sig_sz); + + CMD.header_sz = 2 * sig_sz; + *sz = sig_sz; + } +#endif /* WOLFSSL_HAVE_XMSS */ +#ifdef WOLFSSL_WC_DILITHIUM + else if (*sign == SIGN_ML_DSA) { + int ml_dsa_ret = 0; + int sig_sz = 0; + + ml_dsa_ret = wc_MlDsaKey_Init(&key.ml_dsa, NULL, INVALID_DEVID); + if (ml_dsa_ret != 0) { + fprintf(stderr, "error: wc_MlDsaKey_Init returned %d\n", ml_dsa_ret); + exit(1); + } + + ml_dsa_ret = wc_MlDsaKey_SetParams(&key.ml_dsa, ML_DSA_LEVEL); + if (ml_dsa_ret != 0) { + fprintf(stderr, "error: wc_MlDsaKey_SetParamStr(%d)" \ + " returned %d\n", ML_DSA_LEVEL, ml_dsa_ret); + exit(1); + } + + printf("info: using ML-DSA parameters: %d\n", ML_DSA_LEVEL); + + ml_dsa_ret = wc_MlDsaKey_GetSigLen(&key.ml_dsa, &sig_sz); + if (ml_dsa_ret != 0) { + fprintf(stderr, "error: wc_MlDsaKey_GetSigLen returned %d\n", + ml_dsa_ret); + exit(1); + } + + DEBUG_PRINT("info: ML-DSA signature size: %d\n", sig_sz); + + CMD.header_sz = 2 * sig_sz; + *sz = sig_sz; + } +#endif /* WOLFSSL_WC_DILITHIUM */ +} + int main(int argc, char** argv) { int ret = 0; @@ -1871,11 +2175,12 @@ int main(int argc, char** argv) char* tmpstr; const char* sign_str = "AUTO"; const char* hash_str = "SHA256"; + const char* secondary_sign_str = "NONE"; uint8_t buf[PATH_MAX-32]; /* leave room to avoid "directive output may be truncated" */ uint8_t *pubkey = NULL; uint32_t pubkey_sz = 0; - uint8_t *kbuf=NULL, *key_buffer; - uint32_t key_buffer_sz; + uint8_t *kbuf=NULL, *key_buffer, *key_buffer2; + uint32_t key_buffer_sz, key_buffer_sz2; #ifdef DEBUG_SIGNTOOL wolfSSL_Debugging_ON(); @@ -1897,67 +2202,151 @@ int main(int argc, char** argv) CMD.sign = NO_SIGN; sign_str = "NONE"; } else if (strcmp(argv[i], "--ed25519") == 0) { - CMD.sign = SIGN_ED25519; - sign_str = "ED25519"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_ED25519; + secondary_sign_str = "ED25519"; + } else { + CMD.sign = SIGN_ED25519; + sign_str = "ED25519"; + } } else if (strcmp(argv[i], "--ed448") == 0) { - CMD.sign = SIGN_ED448; - sign_str = "ED448"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_ED448; + secondary_sign_str = "ED448"; + } else { + CMD.sign = SIGN_ED448; + sign_str = "ED448"; + } } else if (strcmp(argv[i], "--ecc256") == 0) { - CMD.sign = SIGN_ECC256; - sign_str = "ECC256"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_ECC256; + secondary_sign_str = "ECC256"; + } else { + CMD.sign = SIGN_ECC256; + sign_str = "ECC256"; + } } else if (strcmp(argv[i], "--ecc384") == 0) { - CMD.sign = SIGN_ECC384; - sign_str = "ECC384"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_ECC384; + secondary_sign_str = "ECC384"; + } else { + CMD.sign = SIGN_ECC384; + sign_str = "ECC384"; + } } else if (strcmp(argv[i], "--ecc521") == 0) { - CMD.sign = SIGN_ECC521; - sign_str = "ECC521"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_ECC521; + secondary_sign_str = "ECC521"; + } else { + CMD.sign = SIGN_ECC521; + sign_str = "ECC521"; + } } else if (strcmp(argv[i], "--rsa2048enc") == 0) { - CMD.sign = SIGN_RSA2048; - sign_str = "RSA2048ENC"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSA2048; + secondary_sign_str = "RSA2048ENC"; + } else { + CMD.sign = SIGN_RSA2048; + sign_str = "RSA2048ENC"; + } CMD.sign_wenc = 1; } else if (strcmp(argv[i], "--rsa2048") == 0) { - CMD.sign = SIGN_RSA2048; - sign_str = "RSA2048"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSA2048; + secondary_sign_str = "RSA2048"; + } else { + CMD.sign = SIGN_RSA2048; + sign_str = "RSA2048"; + } } else if (strcmp(argv[i], "--rsa3072enc") == 0) { - CMD.sign = SIGN_RSA3072; - sign_str = "RSA3072ENC"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSA3072; + secondary_sign_str = "RSA3072ENC"; + } else { + CMD.sign = SIGN_RSA3072; + sign_str = "RSA3072ENC"; + } CMD.sign_wenc = 1; } else if (strcmp(argv[i], "--rsa3072") == 0) { - CMD.sign = SIGN_RSA3072; - sign_str = "RSA3072"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSA3072; + secondary_sign_str = "RSA3072"; + } else { + CMD.sign = SIGN_RSA3072; + sign_str = "RSA3072"; + } } else if (strcmp(argv[i], "--rsa4096enc") == 0) { - CMD.sign = SIGN_RSA4096; - sign_str = "RSA4096ENC"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSA4096; + secondary_sign_str = "RSA4096ENC"; + } else { + CMD.sign = SIGN_RSA4096; + sign_str = "RSA4096ENC"; + } CMD.sign_wenc = 1; } else if (strcmp(argv[i], "--rsa4096") == 0) { - CMD.sign = SIGN_RSA4096; - sign_str = "RSA4096"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSA4096; + secondary_sign_str = "RSA4096"; + } else { + CMD.sign = SIGN_RSA4096; + sign_str = "RSA4096"; + } } #ifdef WOLFSSL_HAVE_LMS else if (strcmp(argv[i], "--lms") == 0) { - CMD.sign = SIGN_LMS; - sign_str = "LMS"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_LMS; + secondary_sign_str = "LMS"; + } else { + CMD.sign = SIGN_LMS; + sign_str = "LMS"; + } } #endif #ifdef WOLFSSL_HAVE_XMSS else if (strcmp(argv[i], "--xmss") == 0) { - CMD.sign = SIGN_XMSS; - sign_str = "XMSS"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_XMSS; + secondary_sign_str = "XMSS"; + } else { + CMD.sign = SIGN_XMSS; + sign_str = "XMSS"; + } } #endif #ifdef HAVE_DILITHIUM else if (strcmp(argv[i], "--ml_dsa") == 0) { - CMD.sign = SIGN_ML_DSA; - sign_str = "ML-DSA"; + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_ML_DSA; + secondary_sign_str = "ML-DSA"; + } else { + CMD.sign = SIGN_ML_DSA; + sign_str = "ML-DSA"; + } } #endif else if (strcmp(argv[i], "--sha256") == 0) { @@ -2135,13 +2524,34 @@ int main(int argc, char** argv) break; } } + if ((CMD.sign == CMD.secondary_sign) && (CMD.hybrid)) { + printf("Warning: Duplicate signature algorithm detected. Fix your command line!\n"); + CMD.hybrid = 0; + CMD.secondary_key_file = NULL; + CMD.secondary_signature_sz = 0; + } + if (CMD.sign != NO_SIGN) { - CMD.image_file = argv[i+1]; - CMD.key_file = argv[i+2]; - CMD.fw_version = argv[i+3]; - if (CMD.manual_sign) { - CMD.signature_file = argv[i+4]; + if (CMD.hybrid) { + printf("Parsing arguments in hybrid mode\n"); + CMD.image_file = argv[i+1]; + CMD.key_file = argv[i+2]; + CMD.secondary_key_file = argv[i+3]; + CMD.fw_version = argv[i+4]; + if (CMD.manual_sign) { + CMD.signature_file = argv[i+5]; + } + printf("Secondary private key: %s\n", CMD.secondary_key_file); + printf("Secondary cipher: %s\n", secondary_sign_str); + printf("Version: %s\n", CMD.fw_version); + } else { + CMD.image_file = argv[i+1]; + CMD.key_file = argv[i+2]; + CMD.fw_version = argv[i+3]; + if (CMD.manual_sign) { + CMD.signature_file = argv[i+4]; + } } } else { CMD.image_file = argv[i+1]; @@ -2154,7 +2564,7 @@ int main(int argc, char** argv) if (tmpstr) { *tmpstr = '\0'; /* null terminate at last "." */ } - snprintf(CMD.output_image_file, sizeof(CMD.output_image_file), + snprintf(CMD.output_image_file, sizeof(CMD.output_image_file) - 1, "%s_v%s_%s.bin", (char*)buf, CMD.fw_version, CMD.sha_only ? "digest" : "signed"); @@ -2182,7 +2592,11 @@ int main(int argc, char** argv) printf("Selected cipher: %s\n", sign_str); printf("Selected hash : %s\n", hash_str); if (CMD.sign != NO_SIGN) { - printf("Public key: %s\n", CMD.key_file); + printf("Private key: %s\n", CMD.key_file); + } + if (CMD.hybrid) { + printf("Secondary cipher: %s\n", secondary_sign_str); + printf("Secondary private key: %s\n", CMD.secondary_key_file); } if (CMD.delta) { printf("Delta Base file: %s\n", CMD.delta_base_file); @@ -2226,151 +2640,10 @@ int main(int argc, char** argv) } } - /* get header and signature sizes */ - if (CMD.sign == SIGN_ED25519) { - if (CMD.header_sz < 256) - CMD.header_sz = 256; - CMD.signature_sz = 64; - } - else if (CMD.sign == SIGN_ED448) { - if (CMD.header_sz < 512) - CMD.header_sz = 512; - CMD.signature_sz = 114; - } - else if (CMD.sign == SIGN_ECC256) { - if (CMD.header_sz < 256) - CMD.header_sz = 256; - CMD.signature_sz = 64; - } - else if (CMD.sign == SIGN_ECC384) { - if (CMD.header_sz < 512) - CMD.header_sz = 512; - CMD.signature_sz = 96; - } - else if (CMD.sign == SIGN_ECC521) { - if (CMD.header_sz < 512) - CMD.header_sz = 512; - CMD.signature_sz = 132; - } - else if (CMD.sign == SIGN_RSA2048) { - if (CMD.header_sz < 512) - CMD.header_sz = 512; - CMD.signature_sz = 256; - } - else if (CMD.sign == SIGN_RSA3072) { - if ((CMD.header_sz < 1024) && (CMD.hash_algo != HASH_SHA256)) - CMD.header_sz = 1024; - if (CMD.header_sz < 512) - CMD.header_sz = 512; - CMD.signature_sz = 384; - } - else if (CMD.sign == SIGN_RSA4096) { - if (CMD.header_sz < 1024) - CMD.header_sz = 1024; - CMD.signature_sz = 512; - } -#ifdef WOLFSSL_HAVE_LMS - else if (CMD.sign == SIGN_LMS) { - int lms_ret = 0; - word32 sig_sz = 0; - - lms_ret = wc_LmsKey_Init(&key.lms, NULL, INVALID_DEVID); - if (lms_ret != 0) { - fprintf(stderr, "error: wc_LmsKey_Init returned %d\n", lms_ret); - exit(1); - } - - lms_ret = wc_LmsKey_SetParameters(&key.lms, LMS_LEVELS, - LMS_HEIGHT, LMS_WINTERNITZ); - if (lms_ret != 0) { - fprintf(stderr, "error: wc_LmsKey_SetParameters(%d, %d, %d)" \ - " returned %d\n", LMS_LEVELS, LMS_HEIGHT, - LMS_WINTERNITZ, ret); - exit(1); - } - - printf("info: using LMS parameters: L%d-H%d-W%d\n", LMS_LEVELS, - LMS_HEIGHT, LMS_WINTERNITZ); - - lms_ret = wc_LmsKey_GetSigLen(&key.lms, &sig_sz); - if (lms_ret != 0) { - fprintf(stderr, "error: wc_LmsKey_GetSigLen returned %d\n", - lms_ret); - exit(1); - } - - printf("info: LMS signature size: %d\n", sig_sz); - - CMD.header_sz = 2 * sig_sz; - CMD.signature_sz = sig_sz; - } -#endif /* WOLFSSL_HAVE_LMS */ -#ifdef WOLFSSL_HAVE_XMSS - else if (CMD.sign == SIGN_XMSS) { - int xmss_ret = 0; - word32 sig_sz = 0; - - xmss_ret = wc_XmssKey_Init(&key.xmss, NULL, INVALID_DEVID); - if (xmss_ret != 0) { - fprintf(stderr, "error: wc_XmssKey_Init returned %d\n", xmss_ret); - exit(1); - } - - xmss_ret = wc_XmssKey_SetParamStr(&key.xmss, WOLFBOOT_XMSS_PARAMS); - if (xmss_ret != 0) { - fprintf(stderr, "error: wc_XmssKey_SetParamStr(%s)" \ - " returned %d\n", WOLFBOOT_XMSS_PARAMS, ret); - exit(1); - } - - printf("info: using XMSS parameters: %s\n", WOLFBOOT_XMSS_PARAMS); - - xmss_ret = wc_XmssKey_GetSigLen(&key.xmss, &sig_sz); - if (xmss_ret != 0) { - fprintf(stderr, "error: wc_XmssKey_GetSigLen returned %d\n", - xmss_ret); - exit(1); - } - - printf("info: XMSS signature size: %d\n", sig_sz); - - CMD.header_sz = 2 * sig_sz; - CMD.signature_sz = sig_sz; - } -#endif /* WOLFSSL_HAVE_XMSS */ -#ifdef WOLFSSL_WC_DILITHIUM - else if (CMD.sign == SIGN_ML_DSA) { - int ml_dsa_ret = 0; - int sig_sz = 0; - - ml_dsa_ret = wc_MlDsaKey_Init(&key.ml_dsa, NULL, INVALID_DEVID); - if (ml_dsa_ret != 0) { - fprintf(stderr, "error: wc_MlDsaKey_Init returned %d\n", ml_dsa_ret); - exit(1); - } - - ml_dsa_ret = wc_MlDsaKey_SetParams(&key.ml_dsa, ML_DSA_LEVEL); - if (ml_dsa_ret != 0) { - fprintf(stderr, "error: wc_MlDsaKey_SetParamStr(%d)" \ - " returned %d\n", ML_DSA_LEVEL, ret); - exit(1); - } - - printf("info: using ML-DSA parameters: %d\n", ML_DSA_LEVEL); - - ml_dsa_ret = wc_MlDsaKey_GetSigLen(&key.ml_dsa, &sig_sz); - if (ml_dsa_ret != 0) { - fprintf(stderr, "error: wc_MlDsaKey_GetSigLen returned %d\n", - ml_dsa_ret); - exit(1); - } - - printf("info: ML-DSA signature size: %d\n", sig_sz); - - CMD.header_sz = 2 * sig_sz; - CMD.signature_sz = sig_sz; + set_signature_sizes(0); + if (CMD.hybrid) { + set_signature_sizes(1); } -#endif /* WOLFSSL_WC_DILITHIUM */ if (((CMD.sign != NO_SIGN) && (CMD.signature_sz == 0)) || CMD.header_sz == 0) { @@ -2384,12 +2657,30 @@ int main(int argc, char** argv) "*** Image will not be authenticated!\n" "*** SECURE BOOT DISABLED.\n"); } else { - kbuf = load_key(&key_buffer, &key_buffer_sz, &pubkey, &pubkey_sz); + kbuf = load_key(&key_buffer, &key_buffer_sz, &pubkey, &pubkey_sz, 0); if (!kbuf) { exit(1); } } /* CMD.sign != NO_SIGN */ - make_header(pubkey, pubkey_sz, CMD.image_file, CMD.output_image_file); + + if (CMD.hybrid) { + uint8_t *kbuf2 = NULL; + uint8_t *pubkey2 = NULL; + uint32_t pubkey_sz2; + DEBUG_PRINT("Loading secondary key\n"); + kbuf2 = load_key(&key_buffer2, &key_buffer_sz2, &pubkey2, &pubkey_sz2, 1); + printf("Creating hybrid signature\n"); + make_hybrid_header(pubkey, pubkey_sz, CMD.image_file, CMD.output_image_file, + pubkey2, pubkey_sz2); + DEBUG_PRINT("Signature size: %u\n", CMD.signature_sz); + DEBUG_PRINT("Secondary signature size: %u\n", CMD.secondary_signature_sz); + DEBUG_PRINT("Header size: %u\n", CMD.header_sz); + if (kbuf2) + free(kbuf2); + } else { + make_header(pubkey, pubkey_sz, CMD.image_file, CMD.output_image_file); + } + if (CMD.delta) { if (CMD.encrypt) diff --git a/tools/scripts/benchmark.sh b/tools/scripts/benchmark.sh index 8caa1efc0..a76d60ce6 100755 --- a/tools/scripts/benchmark.sh +++ b/tools/scripts/benchmark.sh @@ -44,7 +44,7 @@ function set_benchmark { echo -n " | " make clean &>/dev/null make keysclean &>/dev/null - make $@ factory.bin &>/dev/null || make $@ factory.bin + make $@ &>/dev/null || make $@ factory.bin make $@ stack-usage &>/dev/null make $@ image-header-size &>/dev/null # Bootloader size @@ -95,4 +95,6 @@ set_benchmark "ML_DSA-65" SIGN=ML_DSA ML_DSA_LEVEL=3 IMAGE_SIGNATURE_SIZE=3309 I set_benchmark "ML_DSA-87" SIGN=ML_DSA ML_DSA_LEVEL=5 IMAGE_SIGNATURE_SIZE=4627 IMAGE_HEADER_SIZE=12288 set_benchmark "LMS 1-10-8" SIGN=LMS LMS_LEVELS=1 LMS_HEIGHT=10 LMS_WINTERNITZ=8 IMAGE_HEADER_SIZE=4096 IMAGE_SIGNATURE_SIZE=1456 set_benchmark "XMSS-SHA2_10_256'" XMSS_PARAMS='XMSS-SHA2_10_256' SIGN=XMSS IMAGE_SIGNATURE_SIZE=2500 IMAGE_HEADER_SIZE=8192 +set_benchmark "ML_DSA-65 hybrid with ECDSA384" SIGN=ML_DSA ML_DSA_LEVEL=3 IMAGE_SIGNATURE_SIZE=3309 IMAGE_HEADER_SIZE=8192 SIGN_SECONDARY=ECC384 WOLFBOOT_UNIVERSAL_KEYSTORE=1 +set_benchmark "ML_DSA-87 hybrid with ECDSA521" SIGN=ML_DSA ML_DSA_LEVEL=5 IMAGE_SIGNATURE_SIZE=4627 IMAGE_HEADER_SIZE=12288 SIGN_SECONDARY=ECC521 WOLFBOOT_UNIVERSAL_KEYSTORE=1 diff --git a/tools/test.mk b/tools/test.mk index 36cae4a04..46c21781a 100644 --- a/tools/test.mk +++ b/tools/test.mk @@ -986,13 +986,13 @@ test-all: clean test-size-all: - make test-size SIGN=NONE LIMIT=4816 NO_ARM_ASM=1 + make test-size SIGN=NONE LIMIT=4840 NO_ARM_ASM=1 make keysclean - make test-size SIGN=ED25519 LIMIT=11396 NO_ARM_ASM=1 + make test-size SIGN=ED25519 LIMIT=11428 NO_ARM_ASM=1 make keysclean - make test-size SIGN=ECC256 LIMIT=17936 NO_ARM_ASM=1 + make test-size SIGN=ECC256 LIMIT=17948 NO_ARM_ASM=1 make clean - make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13480 NO_ARM_ASM=1 + make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13492 NO_ARM_ASM=1 make keysclean make test-size SIGN=RSA2048 LIMIT=11212 NO_ARM_ASM=1 make clean @@ -1002,11 +1002,11 @@ test-size-all: make clean make test-size SIGN=RSA4096 NO_ASM=1 LIMIT=12076 NO_ARM_ASM=1 make keysclean - make test-size SIGN=ECC384 LIMIT=17504 NO_ARM_ASM=1 + make test-size SIGN=ECC384 LIMIT=17516 NO_ARM_ASM=1 make clean - make test-size SIGN=ECC384 NO_ASM=1 LIMIT=14872 NO_ARM_ASM=1 + make test-size SIGN=ECC384 NO_ASM=1 LIMIT=14884 NO_ARM_ASM=1 make keysclean - make test-size SIGN=ED448 LIMIT=13408 NO_ARM_ASM=1 + make test-size SIGN=ED448 LIMIT=13440 NO_ARM_ASM=1 make keysclean make test-size SIGN=RSA3072 LIMIT=11352 NO_ARM_ASM=1 make clean @@ -1014,9 +1014,9 @@ test-size-all: make keysclean make test-size SIGN=LMS LMS_LEVELS=2 LMS_HEIGHT=5 LMS_WINTERNITZ=8 \ WOLFBOOT_SMALL_STACK=0 IMAGE_SIGNATURE_SIZE=2644 \ - IMAGE_HEADER_SIZE?=5288 LIMIT=7504 NO_ARM_ASM=1 + IMAGE_HEADER_SIZE?=5288 LIMIT=7516 NO_ARM_ASM=1 make keysclean make test-size SIGN=XMSS XMSS_PARAMS='XMSS-SHA2_10_256' \ IMAGE_SIGNATURE_SIZE=2500 IMAGE_HEADER_SIZE?=4096 \ - LIMIT=8220 NO_ARM_ASM=1 + LIMIT=8232 NO_ARM_ASM=1 make keysclean diff --git a/tools/tpm/Makefile b/tools/tpm/Makefile index 4ac391ab2..07dbb6e2b 100644 --- a/tools/tpm/Makefile +++ b/tools/tpm/Makefile @@ -12,8 +12,8 @@ LD = gcc WOLFBOOTDIR = ../.. WOLFDIR = $(WOLFBOOTDIR)/lib/wolfssl/ WOLFTPMDIR = $(WOLFBOOTDIR)/lib/wolfTPM/ -CFLAGS = -Wall -Wextra -Werror -CFLAGS += -DWOLFSSL_USER_SETTINGS -DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM -DHAVE_NETDB_H +CFLAGS = -Wall -Wextra -Werror -Wno-unused-function +CFLAGS += -DWOLFSSL_USER_SETTINGS -DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM -DHAVE_NETDB_H -DWOLFBOOT_SIGN_$(SIGN) CFLAGS += -DXSTRTOL=strtol CFLAGS += -I. -I$(WOLFDIR) -I$(WOLFTPMDIR) -I$(WOLFBOOTDIR)/include LDFLAGS = diff --git a/tools/tpm/policy_create.c b/tools/tpm/policy_create.c index dc53534c9..7143d7066 100644 --- a/tools/tpm/policy_create.c +++ b/tools/tpm/policy_create.c @@ -29,7 +29,7 @@ #include #include #include -#include "keystore.h" +#include "wolfboot/wolfboot.h" #include "tpm.h" #define DEFAULT_PCR 16 diff --git a/tools/tpm/rot.c b/tools/tpm/rot.c index 37802f5b8..9bc53f80a 100644 --- a/tools/tpm/rot.c +++ b/tools/tpm/rot.c @@ -24,7 +24,7 @@ #include #include #include -#include "keystore.h" +#include "wolfboot/wolfboot.h" #include "tpm.h" #include diff --git a/tools/unit-tests/unit-image.c b/tools/unit-tests/unit-image.c index 121152601..41a2d69bc 100644 --- a/tools/unit-tests/unit-image.c +++ b/tools/unit-tests/unit-image.c @@ -43,6 +43,7 @@ #define ENCRYPT_KEY "123456789abcdef0123456789abcdef0123456789abcdef" #define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ECC256 +#define WOLFBOOT_SIGN_PRIMARY_ECC256 #include #include @@ -289,17 +290,17 @@ START_TEST(test_verify_signature) test_img.fw_size = test_img_len; test_img.fw_base = 0; - wolfBoot_verify_signature(0, NULL, NULL); + wolfBoot_verify_signature_ecc(0, NULL, NULL); ck_assert_int_eq(verify_called, 0); ecc_init_fail = 1; - wolfBoot_verify_signature(0, NULL, pubkey); + wolfBoot_verify_signature_ecc(0, NULL, pubkey); ck_assert_int_eq(verify_called, 0); ecc_init_fail = 0; verify_called = 0; ecc_import_fail = 1; - wolfBoot_verify_signature(0, NULL, pubkey); + wolfBoot_verify_signature_ecc(0, NULL, pubkey); ck_assert_int_eq(verify_called, 0); ecc_init_fail = 0; @@ -309,7 +310,7 @@ START_TEST(test_verify_signature) ext_flash_erase(0, 2 * WOLFBOOT_SECTOR_SIZE); ext_flash_write(0, test_img_v200000000_signed_bin, test_img_len); - wolfBoot_verify_signature(0, &test_img, pubkey); + wolfBoot_verify_signature_ecc(0, &test_img, pubkey); ck_assert_int_eq(verify_called, 1); } END_TEST