diff --git a/.github/workflows/test-sunnyday-simulator.yml b/.github/workflows/test-sunnyday-simulator.yml index f8b3dd4b73..ebef5bbec3 100644 --- a/.github/workflows/test-sunnyday-simulator.yml +++ b/.github/workflows/test-sunnyday-simulator.yml @@ -171,6 +171,66 @@ jobs: run: | tools/scripts/sim-sunnyday-update.sh + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS2048) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS2048 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS2048, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS2048 WOLFBOOT_SMALL_STACK=1 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS3072) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS3072 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS3072, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS3072 WOLFBOOT_SMALL_STACK=1 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS4096) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS4096 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS4096, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS4096 WOLFBOOT_SMALL_STACK=1 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + # 32 Bit simulator, FASTMATH # - name: make clean @@ -301,6 +361,66 @@ jobs: run: | tools/scripts/sim-sunnyday-update.sh + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS2048, FASTMATH) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS2048 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS2048, FASTMATH, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS2048 WOLFBOOT_SMALL_STACK=1 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS3072, FASTMATH) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS3072 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS3072, FASTMATH, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS3072 WOLFBOOT_SMALL_STACK=1 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS4096, FASTMATH) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS4096 SPMATH=0 WOLFBOOT_HUGE_STACK=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS4096, FASTMATH, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS4096 WOLFBOOT_SMALL_STACK=1 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + # 64 Bit simulator, SP_MATH # @@ -432,6 +552,66 @@ jobs: run: | tools/scripts/sim-sunnyday-update.sh + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS2048) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS2048 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS2048, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS2048 WOLFBOOT_SMALL_STACK=1 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS3072) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS3072 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS3072, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS3072 WOLFBOOT_SMALL_STACK=1 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS4096) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS4096 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS4096, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS4096 WOLFBOOT_SMALL_STACK=1 SPMATH=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + # 64 Bit simulator, FASTMATH # - name: make clean @@ -562,6 +742,66 @@ jobs: run: | tools/scripts/sim-sunnyday-update.sh + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS2048, FASTMATH) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS2048 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS2048, FASTMATH, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS2048 WOLFBOOT_SMALL_STACK=1 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS3072, FASTMATH) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS3072 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS3072, FASTMATH, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS3072 WOLFBOOT_SMALL_STACK=1 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Cleanup to change key type + run: | + make keysclean + + - name: Build wolfboot.elf (RSAPSS4096, FASTMATH) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS4096 SPMATH=0 WOLFBOOT_HUGE_STACK=1 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + + - name: Build wolfboot.elf (RSAPSS4096, FASTMATH, WOLFBOOT_SMALL_STACK) + run: | + make clean && make test-sim-internal-flash-with-update SIGN=RSAPSS4096 WOLFBOOT_SMALL_STACK=1 SPMATH=0 + + - name: Run sunny day update test + run: | + tools/scripts/sim-sunnyday-update.sh + - name: Run sunny day LMS update test run: | tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-lms.config diff --git a/config/examples/sim-rsapss2048.config b/config/examples/sim-rsapss2048.config new file mode 100644 index 0000000000..8effe6e57c --- /dev/null +++ b/config/examples/sim-rsapss2048.config @@ -0,0 +1,21 @@ +ARCH=sim +TARGET=sim +SIGN?=RSAPSS2048 +HASH?=SHA256 +WOLFBOOT_SMALL_STACK?=0 +SPI_FLASH=0 +DEBUG=1 + +# 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/include/image.h b/include/image.h index c9e7fcba10..81a6103686 100644 --- a/include/image.h +++ b/include/image.h @@ -68,6 +68,11 @@ extern "C" { defined (WOLFBOOT_SIGN_RSA4096ENC) #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_rsa #endif +#if defined (WOLFBOOT_SIGN_RSAPSS2048) || \ + defined (WOLFBOOT_SIGN_RSAPSS3072) || \ + defined (WOLFBOOT_SIGN_RSAPSS4096) +#define wolfBoot_verify_signature_primary wolfBoot_verify_signature_rsa_pss +#endif #if defined (WOLFBOOT_SIGN_ECC256) || \ defined (WOLFBOOT_SIGN_ECC384) || \ defined (WOLFBOOT_SIGN_ECC521) @@ -97,6 +102,11 @@ extern "C" { defined (WOLFBOOT_SIGN_SECONDARY_RSA4096ENC) #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_rsa #endif +#if defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) +#define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_rsa_pss +#endif #if defined (WOLFBOOT_SIGN_SECONDARY_ECC256) || \ defined (WOLFBOOT_SIGN_SECONDARY_ECC384) || \ defined (WOLFBOOT_SIGN_SECONDARY_ECC521) @@ -112,6 +122,12 @@ extern "C" { #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ml_dsa #endif +/* Thin wrappers: dispatch RSA / RSA-PSS to the unified verify function */ +#define wolfBoot_verify_signature_rsa(ks, img, sig) \ + wolfBoot_verify_signature_rsa_common(ks, img, sig, 0) +#define wolfBoot_verify_signature_rsa_pss(ks, img, sig) \ + wolfBoot_verify_signature_rsa_common(ks, img, sig, 1) + #if defined(WOLFBOOT_TPM) && defined (WOLFBOOT_TPM_VERIFY) #undef wolfBoot_verify_signature_primary #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_tpm @@ -372,6 +388,8 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( * double checking its return value contains a valid * len (>= WOLFBOOT_SHA_DIGEST_SIZE). * + * Uses GAS local numeric labels (1f/1:) so the macro can be safely expanded + * multiple times in the same function (e.g. RSA PKCS#1.5 + RSA-PSS paths). */ #define RSA_VERIFY_FN(ret,fn,...) \ { \ @@ -390,22 +408,22 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( asm volatile("cmp r0, r2":::"cc"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("cmp r0, r2":::"cc"); \ - asm volatile("blt nope"); \ + asm volatile("blt 1f"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("cmp r0, r2":::"cc"); \ - asm volatile("blt nope"); \ + asm volatile("blt 1f"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("cmp r0, r2":::"cc"); \ - asm volatile("blt nope"); \ + asm volatile("blt 1f"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("cmp r0, r2":::"cc"); \ asm volatile("cmp r0, r2":::"cc"); \ - asm volatile("blt nope"); \ + asm volatile("blt 1f"); \ /* Return value is set here in case of success */ \ ret = tmp_ret; \ - asm volatile("nope:"); \ + asm volatile("1:"); \ asm volatile("nop"); \ } @@ -414,12 +432,14 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( * * Compare the digest twice, then confirm via * wolfBoot_image_confirm_signature_ok(); + * + * Uses GAS local numeric labels (2f/2:) for safe multi-expansion. */ #define RSA_VERIFY_HASH(img,digest) \ { \ volatile int compare_res; \ if (!img || !digest) \ - asm volatile("b hnope"); \ + asm volatile("b 2f"); \ /* Redundant set of r0=50*/ \ asm volatile("mov r0, #50":::"r0"); \ asm volatile("mov r0, #50":::"r0"); \ @@ -429,19 +449,19 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne hnope":::"cc"); \ + asm volatile("bne 2f":::"cc"); \ asm volatile("cmp r0, #0"); \ asm volatile("cmp r0, #0"); \ asm volatile("cmp r0, #0"); \ - asm volatile("bne hnope":::"cc"); \ + asm volatile("bne 2f":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne hnope"); \ + asm volatile("bne 2f"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne hnope"); \ + asm volatile("bne 2f"); \ /* Repeat memcmp call */ \ compare_res = XMEMCMP(digest, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); \ compare_res; \ @@ -449,22 +469,85 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne hnope"); \ + asm volatile("bne 2f"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("bne 2f"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("bne 2f"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("bne 2f"); \ + /* Confirm that the signature is OK */ \ + wolfBoot_image_confirm_signature_ok(img); \ + asm volatile("2:"); \ + asm volatile("nop"); \ + } + +/** + * Second part of RSA-PSS verification. + * + * Call wc_RsaPSS_CheckPadding twice, then confirm via + * wolfBoot_image_confirm_signature_ok(); + * + * Uses GAS local numeric labels (3f/3:) for safe multi-expansion. + */ +#define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \ + { \ + volatile int pss_res; \ + if (!img || !pss_data) \ + asm volatile("b 3f"); \ + /* Redundant set of r0=50*/ \ + asm volatile("mov r0, #50":::"r0"); \ + asm volatile("mov r0, #50":::"r0"); \ + asm volatile("mov r0, #50":::"r0"); \ + pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \ + pss_data, pss_data_sz, hash_type); \ + /* Redundant checks that ensure the function actually returned 0 */ \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("bne 3f":::"cc"); \ + asm volatile("cmp r0, #0"); \ + asm volatile("cmp r0, #0"); \ + asm volatile("cmp r0, #0"); \ + asm volatile("bne 3f":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("bne 3f"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("bne 3f"); \ + /* Repeat wc_RsaPSS_CheckPadding call */ \ + pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \ + pss_data, pss_data_sz, hash_type); \ + pss_res; \ + /* Redundant checks that ensure the function actually returned 0 */ \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("cmp r0, #0":::"cc"); \ + asm volatile("bne 3f"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne hnope"); \ + asm volatile("bne 3f"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne hnope"); \ + asm volatile("bne 3f"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne hnope"); \ + asm volatile("bne 3f"); \ /* Confirm that the signature is OK */ \ wolfBoot_image_confirm_signature_ok(img); \ - asm volatile("hnope:"); \ + asm volatile("3:"); \ asm volatile("nop"); \ } @@ -477,6 +560,8 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( * set the return value accordingly. * * Double check by reading the value in p_res from memory a few times. + * + * Uses GAS local numeric labels (4f/4:) for safe multi-expansion. */ #if defined(__GNUC__) @@ -491,63 +576,63 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ /* Check that res = 1, a few times, reading the value from memory */ \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("cmp r2, #1":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("mvn r3, r2":::"r3"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("cmp r2, #1":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("mvn r3, r2":::"r3"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("cmp r2, #1":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("mvn r3, r2":::"r3"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("cmp r2, #1":::"cc"); \ asm volatile("cmp r2, #1":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ asm volatile("mvn r3, r2":::"r3"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ - asm volatile("bne nope"); \ + asm volatile("bne 4f"); \ /* Confirm that the signature is OK */ \ wolfBoot_image_confirm_signature_ok(img); \ - asm volatile("nope:"); \ + asm volatile("4:"); \ asm volatile("nop") \ #elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__) @@ -1237,6 +1322,11 @@ static void UNUSEDFUNCTION wolfBoot_image_clear_signature_ok( if (XMEMCMP(img->sha_hash, digest, WOLFBOOT_SHA_DIGEST_SIZE) == 0) \ wolfBoot_image_confirm_signature_ok(img); +#define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \ + if (wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \ + pss_data, pss_data_sz, hash_type) == 0) \ + wolfBoot_image_confirm_signature_ok(img); + #define PART_SANITY_CHECK(p) \ if (((p)->hdr_ok != 1) || ((p)->sha_ok != 1) || ((p)->signature_ok != 1)) \ wolfBoot_panic() diff --git a/include/loader.h b/include/loader.h index 9d2ef37653..9eadc1660c 100644 --- a/include/loader.h +++ b/include/loader.h @@ -40,11 +40,25 @@ extern "C" { #define ECC_IMAGE_SIGNATURE_SIZE (132) #endif -#if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) +/* Consolidated RSA-PSS flag: set when any RSA-PSS variant is enabled + * (primary or secondary). Used to guard PSS-specific code paths in the + * unified RSA verify function. */ +#if defined(WOLFBOOT_SIGN_RSAPSS2048) || defined(WOLFBOOT_SIGN_RSAPSS3072) || \ + defined(WOLFBOOT_SIGN_RSAPSS4096) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) +#define WOLFBOOT_SIGN_RSAPSS_ANY +#endif + +#if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ + defined(WOLFBOOT_SIGN_RSAPSS2048) || defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) #define RSA_IMAGE_SIGNATURE_SIZE (256) -#elif defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) +#elif defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ + defined(WOLFBOOT_SIGN_RSAPSS3072) || defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) #define RSA_IMAGE_SIGNATURE_SIZE (384) -#elif defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) +#elif defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ + defined(WOLFBOOT_SIGN_RSAPSS4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) #define RSA_IMAGE_SIGNATURE_SIZE (512) #endif diff --git a/include/user_settings.h b/include/user_settings.h index c681839c07..b30500368f 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -222,12 +222,25 @@ extern int tolower(int c); defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ + defined(WOLFBOOT_SIGN_RSAPSS2048) || \ + defined(WOLFBOOT_SIGN_RSAPSS3072) || \ + defined(WOLFBOOT_SIGN_RSAPSS4096) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) || \ (defined(WOLFCRYPT_SECURE_MODE) && (!defined(PKCS11_SMALL))) # define WC_RSA_BLINDING # define WC_RSA_DIRECT # define RSA_LOW_MEM # define WC_ASN_HASH_SHA256 +# if defined(WOLFBOOT_SIGN_RSAPSS2048) || defined(WOLFBOOT_SIGN_RSAPSS3072) || \ + defined(WOLFBOOT_SIGN_RSAPSS4096) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) +# define WC_RSA_PSS +# endif # if !defined(WOLFBOOT_TPM) && !defined(WOLFCRYPT_SECURE_MODE) && \ !defined(WOLFCRYPT_TEST) && !defined(WOLFCRYPT_BENCHMARK) && \ !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ @@ -235,7 +248,9 @@ extern int tolower(int c); # define WOLFSSL_RSA_VERIFY_INLINE # define WOLFSSL_RSA_VERIFY_ONLY # define WOLFSSL_RSA_PUBLIC_ONLY -# define WC_NO_RSA_OAEP +# if !defined(WC_RSA_PSS) +# define WC_NO_RSA_OAEP +# endif # define NO_RSA_BOUNDS_CHECK # endif # if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH_ALL) @@ -244,7 +259,8 @@ extern int tolower(int c); # define WOLFSSL_SP_SMALL # define WOLFSSL_SP_MATH # endif -# if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) +# if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ + defined(WOLFBOOT_SIGN_RSAPSS2048) || defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) # define FP_MAX_BITS (2048 * 2) # define SP_INT_BITS 2048 # define WOLFSSL_SP_NO_3072 @@ -253,7 +269,8 @@ extern int tolower(int c); # define RSA_MIN_SIZE 2048 # define RSA_MAX_SIZE 2048 # endif -# if defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) +# if defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ + defined(WOLFBOOT_SIGN_RSAPSS3072) || defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) # define FP_MAX_BITS (3072 * 2) # define SP_INT_BITS 3072 # define WOLFSSL_SP_NO_2048 @@ -263,7 +280,8 @@ extern int tolower(int c); # define RSA_MAX_SIZE 3072 # endif -# if defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) +# if defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ + defined(WOLFBOOT_SIGN_RSAPSS4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) # define FP_MAX_BITS (4096 * 2) # define SP_INT_BITS 4096 # define WOLFSSL_SP_NO_2048 diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index 201b232437..79cda35bfd 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -112,16 +112,16 @@ extern "C" { #ifndef IMAGE_HEADER_SIZE /* Largest cases first */ -# if defined(WOLFBOOT_SIGN_RSA4096) +# if defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_RSAPSS4096) # define IMAGE_HEADER_SIZE 1024 - /* RSA3072 + strong hash */ -# elif (defined(WOLFBOOT_SIGN_RSA3072) && \ + /* RSA3072/RSAPSS3072 + strong hash */ +# elif ((defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_RSAPSS3072)) && \ (defined(WOLFBOOT_HASH_SHA384) || defined(WOLFBOOT_HASH_SHA3_384))) # define IMAGE_HEADER_SIZE 1024 - /* RSA2048 + SHA256 */ -# elif defined(WOLFBOOT_SIGN_RSA2048) && defined(WOLFBOOT_HASH_SHA256) + /* RSA2048/RSAPSS2048 + SHA256 */ +# elif (defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_RSAPSS2048)) && defined(WOLFBOOT_HASH_SHA256) # define IMAGE_HEADER_SIZE 512 /* ECC384 requires 512 with SHA256 */ @@ -141,7 +141,7 @@ extern "C" { # define IMAGE_HEADER_SIZE 256 /* Secondary 512-byte fallbacks */ -# elif defined(WOLFBOOT_SIGN_RSA3072) || \ +# elif defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_RSAPSS3072) || \ defined(WOLFBOOT_SIGN_ECC521) || \ defined(WOLFBOOT_SIGN_ED448) || \ defined(WOLFBOOT_HASH_SHA384) || \ @@ -224,7 +224,10 @@ extern "C" { #define AUTH_KEY_ECC521 0x07 #define AUTH_KEY_RSA3072 0x08 #define AUTH_KEY_LMS 0x09 - /* 0x0A...0x0F reserved */ +#define AUTH_KEY_RSAPSS2048 0x0A +#define AUTH_KEY_RSAPSS3072 0x0B +#define AUTH_KEY_RSAPSS4096 0x0C + /* 0x0D...0x0F reserved */ #define AUTH_KEY_XMSS 0x10 #define AUTH_KEY_ML_DSA 0x11 @@ -245,6 +248,9 @@ extern "C" { #define HDR_IMG_TYPE_AUTH_ECC521 (AUTH_KEY_ECC521 << 8) #define HDR_IMG_TYPE_AUTH_RSA3072 (AUTH_KEY_RSA3072 << 8) #define HDR_IMG_TYPE_AUTH_LMS (AUTH_KEY_LMS << 8) +#define HDR_IMG_TYPE_AUTH_RSAPSS2048 (AUTH_KEY_RSAPSS2048 << 8) +#define HDR_IMG_TYPE_AUTH_RSAPSS3072 (AUTH_KEY_RSAPSS3072 << 8) +#define HDR_IMG_TYPE_AUTH_RSAPSS4096 (AUTH_KEY_RSAPSS4096 << 8) #define HDR_IMG_TYPE_AUTH_XMSS (AUTH_KEY_XMSS << 8) #define HDR_IMG_TYPE_AUTH_ML_DSA (AUTH_KEY_ML_DSA << 8) @@ -265,6 +271,9 @@ extern "C" { #define KEYSTORE_PUBKEY_SIZE_RSA2048 320 #define KEYSTORE_PUBKEY_SIZE_RSA3072 448 #define KEYSTORE_PUBKEY_SIZE_RSA4096 576 +#define KEYSTORE_PUBKEY_SIZE_RSAPSS2048 KEYSTORE_PUBKEY_SIZE_RSA2048 +#define KEYSTORE_PUBKEY_SIZE_RSAPSS3072 KEYSTORE_PUBKEY_SIZE_RSA3072 +#define KEYSTORE_PUBKEY_SIZE_RSAPSS4096 KEYSTORE_PUBKEY_SIZE_RSA4096 #define KEYSTORE_PUBKEY_SIZE_LMS 60 #define KEYSTORE_PUBKEY_SIZE_XMSS 68 @@ -439,6 +448,21 @@ extern "C" { # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE # define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA4096 # endif + #elif defined(WOLFBOOT_SIGN_RSAPSS2048) + # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSAPSS2048 + # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE + # define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA2048 + # endif + #elif defined(WOLFBOOT_SIGN_RSAPSS3072) + # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSAPSS3072 + # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE + # define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA3072 + # endif + #elif defined(WOLFBOOT_SIGN_RSAPSS4096) + # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSAPSS4096 + # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE + # define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA4096 + # endif #elif defined(WOLFBOOT_SIGN_LMS) # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_LMS # ifndef WOLFBOOT_UNIVERSAL_KEYSTORE diff --git a/options.mk b/options.mk index ff8df2c4ad..2ec47bc191 100644 --- a/options.mk +++ b/options.mk @@ -298,6 +298,86 @@ ifeq ($(SIGN),ED448) endif endif +ifeq ($(SIGN),RSAPSS2048) + KEYGEN_OPTIONS+=--rsapss2048 + SIGN_OPTIONS+=--rsapss2048 + SIGN_ALG=RSAPSS2048 + WOLFCRYPT_OBJS+= $(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + CFLAGS+=-D"WOLFBOOT_SIGN_RSAPSS2048" $(RSA_EXTRA_CFLAGS) + ifeq ($(WOLFBOOT_SMALL_STACK),1) + ifneq ($(SPMATH),1) + STACK_USAGE=5008 + else + STACK_USAGE=4096 + endif + else + ifneq ($(SPMATH),1) + STACK_USAGE=35952 + else + STACK_USAGE=17568 + endif + endif + ifeq ($(shell test $(IMAGE_HEADER_SIZE) -lt 512; echo $$?),0) + IMAGE_HEADER_SIZE=512 + endif +endif + +ifeq ($(SIGN),RSAPSS3072) + KEYGEN_OPTIONS+=--rsapss3072 + SIGN_OPTIONS+=--rsapss3072 + SIGN_ALG=RSAPSS3072 + WOLFCRYPT_OBJS+= $(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + CFLAGS+=-D"WOLFBOOT_SIGN_RSAPSS3072" $(RSA_EXTRA_CFLAGS) + ifeq ($(WOLFBOOT_SMALL_STACK),1) + ifneq ($(SPMATH),1) + STACK_USAGE=5008 + else + STACK_USAGE=4364 + endif + else + ifneq ($(SPMATH),1) + STACK_USAGE=52592 + else + STACK_USAGE=12288 + endif + endif + ifneq ($(HASH),SHA256) + ifeq ($(shell test $(IMAGE_HEADER_SIZE) -lt 1024; echo $$?),0) + IMAGE_HEADER_SIZE=1024 + endif + endif + ifeq ($(shell test $(IMAGE_HEADER_SIZE) -lt 512; echo $$?),0) + IMAGE_HEADER_SIZE=512 + endif +endif + +ifeq ($(SIGN),RSAPSS4096) + KEYGEN_OPTIONS+=--rsapss4096 + SIGN_OPTIONS+=--rsapss4096 + SIGN_ALG=RSAPSS4096 + WOLFCRYPT_OBJS+= $(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + CFLAGS+=-D"WOLFBOOT_SIGN_RSAPSS4096" $(RSA_EXTRA_CFLAGS) + ifeq ($(WOLFBOOT_SMALL_STACK),1) + ifneq ($(SPMATH),1) + STACK_USAGE=5888 + else + STACK_USAGE=5768 + endif + else + ifneq ($(SPMATH),1) + STACK_USAGE=69232 + else + STACK_USAGE=18064 + endif + endif + ifeq ($(shell test $(IMAGE_HEADER_SIZE) -lt 1024; echo $$?),0) + IMAGE_HEADER_SIZE=1024 + endif +endif + ifneq ($(findstring RSA2048,$(SIGN)),) KEYGEN_OPTIONS+=--rsa2048 ifeq ($(SIGN),RSA2048ENC) @@ -360,7 +440,9 @@ ifneq ($(findstring RSA3072,$(SIGN)),) endif endif ifneq ($(HASH),SHA256) - IMAGE_HEADER_SIZE=1024 + ifeq ($(shell test $(IMAGE_HEADER_SIZE) -lt 1024; echo $$?),0) + IMAGE_HEADER_SIZE=1024 + endif endif ifeq ($(shell test $(IMAGE_HEADER_SIZE) -lt 512; echo $$?),0) IMAGE_HEADER_SIZE=512 @@ -503,6 +585,18 @@ ifneq ($(SIGN_SECONDARY),) WOLFCRYPT_OBJS+=$(RSA_OBJS) WOLFCRYPT_OBJS+=$(MATH_OBJS) endif + ifeq ($(SIGN_SECONDARY),RSAPSS2048) + WOLFCRYPT_OBJS+=$(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + ifeq ($(SIGN_SECONDARY),RSAPSS3072) + WOLFCRYPT_OBJS+=$(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif + ifeq ($(SIGN_SECONDARY),RSAPSS4096) + WOLFCRYPT_OBJS+=$(RSA_OBJS) + WOLFCRYPT_OBJS+=$(MATH_OBJS) + endif ifeq ($(SIGN_SECONDARY),ECC256) WOLFCRYPT_OBJS+=$(ECC_OBJS) WOLFCRYPT_OBJS+=$(MATH_OBJS) diff --git a/src/image.c b/src/image.c index d5ff5f3e1a..a390eefb43 100644 --- a/src/image.c +++ b/src/image.c @@ -364,7 +364,13 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot, defined(WOLFBOOT_SIGN_RSA4096) || \ defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ - defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) + defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ + defined(WOLFBOOT_SIGN_RSAPSS2048) || \ + defined(WOLFBOOT_SIGN_RSAPSS3072) || \ + defined(WOLFBOOT_SIGN_RSAPSS4096) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) || \ + defined(WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) #include #include @@ -424,8 +430,8 @@ static int RsaDecodeSignature(uint8_t** pInput, int inputSz) } #endif /* !NO_RSA_SIG_ENCODING */ -static void wolfBoot_verify_signature_rsa(uint8_t key_slot, - struct wolfBoot_image *img, uint8_t *sig) +static void wolfBoot_verify_signature_rsa_common(uint8_t key_slot, + struct wolfBoot_image *img, uint8_t *sig, int is_pss) { int ret; uint8_t output[RSA_IMAGE_SIGNATURE_SIZE]; @@ -434,6 +440,21 @@ static void wolfBoot_verify_signature_rsa(uint8_t key_slot, struct RsaKey rsa; (void)inOutIdx; + (void)is_pss; + +#ifdef WOLFBOOT_SIGN_RSAPSS_ANY + enum wc_HashType hash_type; + int mgf; +#if defined(WOLFBOOT_HASH_SHA256) + hash_type = WC_HASH_TYPE_SHA256; + mgf = WC_MGF1SHA256; +#elif defined(WOLFBOOT_HASH_SHA384) + hash_type = WC_HASH_TYPE_SHA384; + mgf = WC_MGF1SHA384; +#else + #error "RSA-PSS requires SHA-256 or SHA-384" +#endif +#endif /* WOLFBOOT_SIGN_RSAPSS_ANY */ #if (!defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)) || \ @@ -450,6 +471,10 @@ static void wolfBoot_verify_signature_rsa(uint8_t key_slot, #if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \ defined(WOLFBOOT_RENESAS_TSIP) || \ defined(WOLFBOOT_RENESAS_RSIP) + /* Renesas crypto callback supports RSA PKCS#1 v1.5 only */ +#ifdef WOLFBOOT_SIGN_RSAPSS_ANY + #error "RSA-PSS is not yet supported with Renesas crypto callbacks" +#endif ret = wc_InitRsaKey_ex(&rsa, NULL, RENESAS_DEVID); if (ret == 0) { XMEMCPY(output, sig, RSA_IMAGE_SIGNATURE_SIZE); @@ -513,8 +538,17 @@ static void wolfBoot_verify_signature_rsa(uint8_t key_slot, } #endif /* !WOLFBOOT_USE_WOLFHSM_PUBKEY_ID */ XMEMCPY(output, sig, RSA_IMAGE_SIGNATURE_SIZE); - RSA_VERIFY_FN(ret, wc_RsaSSL_VerifyInline, output, RSA_IMAGE_SIGNATURE_SIZE, - &digest_out, &rsa); +#ifdef WOLFBOOT_SIGN_RSAPSS_ANY + if (is_pss) { + RSA_VERIFY_FN(ret, wc_RsaPSS_VerifyInline, output, + RSA_IMAGE_SIGNATURE_SIZE, &digest_out, hash_type, mgf, + &rsa); + } else +#endif + { + RSA_VERIFY_FN(ret, wc_RsaSSL_VerifyInline, output, + RSA_IMAGE_SIGNATURE_SIZE, &digest_out, &rsa); + } #if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ !defined(WOLFBOOT_USE_WOLFHSM_PUBKEY_ID) /* evict the key after use, since we aren't using the RSA import API */ @@ -539,28 +573,49 @@ static void wolfBoot_verify_signature_rsa(uint8_t key_slot, ret = wc_RsaPublicKeyDecode((byte*)pubkey, &inOutIdx, &rsa, pubkey_sz); if (ret >= 0) { XMEMCPY(output, sig, RSA_IMAGE_SIGNATURE_SIZE); - RSA_VERIFY_FN(ret, - wc_RsaSSL_VerifyInline, output, RSA_IMAGE_SIGNATURE_SIZE, - &digest_out, &rsa); +#ifdef WOLFBOOT_SIGN_RSAPSS_ANY + if (is_pss) { + RSA_VERIFY_FN(ret, + wc_RsaPSS_VerifyInline, output, RSA_IMAGE_SIGNATURE_SIZE, + &digest_out, hash_type, mgf, &rsa); + } else +#endif + { + RSA_VERIFY_FN(ret, + wc_RsaSSL_VerifyInline, output, RSA_IMAGE_SIGNATURE_SIZE, + &digest_out, &rsa); + } } } #endif /* SCE || TSIP */ wc_FreeRsaKey(&rsa); +#ifdef WOLFBOOT_SIGN_RSAPSS_ANY + if (is_pss) { + if (ret >= WOLFBOOT_SHA_DIGEST_SIZE && img && digest_out) { + RSA_PSS_VERIFY_HASH(img, digest_out, ret, hash_type); + } + } else +#endif + { #ifndef NO_RSA_SIG_ENCODING - if (ret > WOLFBOOT_SHA_DIGEST_SIZE) { - /* larger result indicates it might have an ASN.1 encoded header */ - ret = RsaDecodeSignature(&digest_out, ret); - } + if (ret > WOLFBOOT_SHA_DIGEST_SIZE) { + /* larger result indicates it might have an ASN.1 encoded header */ + ret = RsaDecodeSignature(&digest_out, ret); + } #endif - if (ret == WOLFBOOT_SHA_DIGEST_SIZE && img && digest_out) { - RSA_VERIFY_HASH(img, digest_out); + if (ret == WOLFBOOT_SHA_DIGEST_SIZE && img && digest_out) { + RSA_VERIFY_HASH(img, digest_out); + } } } #endif /* WOLFBOOT_SIGN_RSA2048 || WOLFBOOT_SIGN_RSA3072 || \ * WOLFBOOT_SIGN_RSA4096 || WOLFBOOT_SIGN_SECONDARY_RSA2048 || - * WOLFBOOT_SIGN_SECONDARY_RSA3072 || WOLFBOOT_SIGN_SECONDARY_RSA4096 */ + * WOLFBOOT_SIGN_SECONDARY_RSA3072 || WOLFBOOT_SIGN_SECONDARY_RSA4096 || + * WOLFBOOT_SIGN_RSAPSS2048 || WOLFBOOT_SIGN_RSAPSS3072 || + * WOLFBOOT_SIGN_RSAPSS4096 || WOLFBOOT_SIGN_SECONDARY_RSAPSS2048 || + * WOLFBOOT_SIGN_SECONDARY_RSAPSS3072 || WOLFBOOT_SIGN_SECONDARY_RSAPSS4096 */ #ifdef WOLFBOOT_SIGN_LMS #include @@ -2272,7 +2327,10 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) defined (WOLFBOOT_SIGN_RSA4096) || \ defined (WOLFBOOT_SIGN_RSA2048ENC) || \ defined (WOLFBOOT_SIGN_RSA3072ENC) || \ - defined (WOLFBOOT_SIGN_RSA4096ENC) + defined (WOLFBOOT_SIGN_RSA4096ENC) || \ + defined (WOLFBOOT_SIGN_RSAPSS2048) || \ + defined (WOLFBOOT_SIGN_RSAPSS3072) || \ + defined (WOLFBOOT_SIGN_RSAPSS4096) if (stored_signature_size != RSA_IMAGE_SIGNATURE_SIZE) return -1; #elif defined (WOLFBOOT_SIGN_ECC256) || \ @@ -2344,7 +2402,10 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) defined (WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ defined (WOLFBOOT_SIGN_SECONDARY_RSA2048ENC) || \ defined (WOLFBOOT_SIGN_SECONDARY_RSA3072ENC) || \ - defined (WOLFBOOT_SIGN_SECONDARY_RSA4096ENC) + defined (WOLFBOOT_SIGN_SECONDARY_RSA4096ENC) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) expected_secondary_signature_size = RSA_IMAGE_SIGNATURE_SIZE; #elif defined (WOLFBOOT_SIGN_SECONDARY_ECC256) || \ defined (WOLFBOOT_SIGN_SECONDARY_ECC384) || \ diff --git a/src/xmalloc.c b/src/xmalloc.c index 69962d6aec..38cbf6efde 100644 --- a/src/xmalloc.c +++ b/src/xmalloc.c @@ -335,7 +335,9 @@ static struct xmalloc_slot xmalloc_pool[] = { #elif defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_RSA4096) || \ - defined(WOLFBOOT_SIGN_RSA3072) + defined(WOLFBOOT_SIGN_RSA3072) || \ + defined(WOLFBOOT_SIGN_RSAPSS2048) || defined(WOLFBOOT_SIGN_RSAPSS4096) || \ + defined(WOLFBOOT_SIGN_RSAPSS3072) #if defined(WOLFBOOT_HASH_SHA256) || defined(WOLFBOOT_HASH_SHA384) static uint32_t sha_block[HASH_BLOCK_SIZE]; @@ -349,7 +351,7 @@ static uint32_t sha_block[HASH_BLOCK_SIZE]; static uint8_t asncheck_buf[ASNCHECK_BUF_SIZE]; #ifndef USE_FAST_MATH - #ifdef WOLFBOOT_SIGN_RSA2048 + #if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_RSAPSS2048) #define MP_SCHEME "SP RSA2048" #define MP_INT_DYNAMIC_SIZE MP_INT_SIZEOF(MP_BITS_CNT(2048)) #define MP_BIGINT_MODEXP_SIZE (MP_INT_DYNAMIC_SIZE * 4) @@ -362,7 +364,7 @@ static uint8_t asncheck_buf[ASNCHECK_BUF_SIZE]; #define MPDIGIT_BUF1_SIZE (MP_DIGIT_SIZE * (72 * 4 + 3)) static uint8_t mp_digit_buf1[MPDIGIT_BUF1_SIZE]; #endif - #elif defined WOLFBOOT_SIGN_RSA3072 + #elif defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_RSAPSS3072) #define MP_SCHEME "SP RSA3072" #define MP_INT_DYNAMIC_SIZE MP_INT_SIZEOF(MP_BITS_CNT(3072)) #define MP_BIGINT_MODEXP_SIZE (MP_INT_DYNAMIC_SIZE * 4) diff --git a/tools/keytools/keygen.c b/tools/keytools/keygen.c index 97f38340d6..b9a70a93f9 100644 --- a/tools/keytools/keygen.c +++ b/tools/keytools/keygen.c @@ -108,6 +108,9 @@ #define KEYGEN_LMS 9 #define KEYGEN_XMSS 10 #define KEYGEN_ML_DSA 11 +#define KEYGEN_RSAPSS2048 12 +#define KEYGEN_RSAPSS3072 13 +#define KEYGEN_RSAPSS4096 14 /* Globals */ static FILE *fpub, *fpub_image; @@ -296,7 +299,7 @@ static void fwritekey(uint8_t *key, int len, FILE *f) } } -const char KType[][17] = { +const char KType[][21] = { "AUTH_KEY_NONE", "AUTH_KEY_ED25519", "AUTH_KEY_ECC256", @@ -308,10 +311,13 @@ const char KType[][17] = { "AUTH_KEY_RSA3072", "AUTH_KEY_LMS", "AUTH_KEY_XMSS", - "AUTH_KEY_ML_DSA" + "AUTH_KEY_ML_DSA", + "AUTH_KEY_RSAPSS2048", + "AUTH_KEY_RSAPSS3072", + "AUTH_KEY_RSAPSS4096" }; -const char KSize[][29] = { +const char KSize[][32] = { "KEYSTORE_PUBKEY_SIZE_NONE", "KEYSTORE_PUBKEY_SIZE_ED25519", "KEYSTORE_PUBKEY_SIZE_ECC256", @@ -323,10 +329,13 @@ const char KSize[][29] = { "KEYSTORE_PUBKEY_SIZE_RSA3072", "KEYSTORE_PUBKEY_SIZE_LMS", "KEYSTORE_PUBKEY_SIZE_XMSS", - "KEYSTORE_PUBKEY_SIZE_ML_DSA" + "KEYSTORE_PUBKEY_SIZE_ML_DSA", + "KEYSTORE_PUBKEY_SIZE_RSAPSS2048", + "KEYSTORE_PUBKEY_SIZE_RSAPSS3072", + "KEYSTORE_PUBKEY_SIZE_RSAPSS4096" }; -const char KName[][8] = { +const char KName[][12] = { "NONE", "ED25519", "ECC256", @@ -338,7 +347,10 @@ const char KName[][8] = { "RSA3072", "LMS", "XMSS", - "ML_DSA" + "ML_DSA", + "RSAPSS2048", + "RSAPSS3072", + "RSAPSS4096" }; #define MAX_PUBKEYS 64 @@ -446,6 +458,15 @@ static uint32_t get_pubkey_size(uint32_t keyType) case KEYGEN_RSA4096: size = KEYSTORE_PUBKEY_SIZE_RSA4096; break; + case KEYGEN_RSAPSS2048: + size = KEYSTORE_PUBKEY_SIZE_RSA2048; + break; + case KEYGEN_RSAPSS3072: + size = KEYSTORE_PUBKEY_SIZE_RSA3072; + break; + case KEYGEN_RSAPSS4096: + size = KEYSTORE_PUBKEY_SIZE_RSA4096; + break; case KEYGEN_LMS: size = KEYSTORE_PUBKEY_SIZE_LMS; break; @@ -514,7 +535,16 @@ void keystore_add(uint32_t ktype, uint8_t *key, uint32_t sz, const char *keyfile memset(&sl, 0, sizeof(sl)); sl.slot_id = id_slot; - sl.key_type = ktype; + /* Map keygen key type to AUTH_KEY_* value for binary keystore. + * KEYGEN_RSAPSS* values (12-14) differ from AUTH_KEY_RSAPSS* (0x0A-0x0C). */ + if (ktype == KEYGEN_RSAPSS2048) + sl.key_type = AUTH_KEY_RSAPSS2048; + else if (ktype == KEYGEN_RSAPSS3072) + sl.key_type = AUTH_KEY_RSAPSS3072; + else if (ktype == KEYGEN_RSAPSS4096) + sl.key_type = AUTH_KEY_RSAPSS4096; + else + sl.key_type = ktype; sl.part_id_mask = id_mask; sl.pubkey_size = get_pubkey_size(ktype); @@ -541,7 +571,8 @@ void keystore_add(uint32_t ktype, uint8_t *key, uint32_t sz, const char *keyfile } -static void keygen_rsa(const char *keyfile, int kbits, uint32_t id_mask) +static void keygen_rsa(const char *keyfile, int kbits, uint32_t id_mask, + int ktype) { RsaKey k; uint8_t priv_der[4096], pub_der[2048]; @@ -583,12 +614,7 @@ static void keygen_rsa(const char *keyfile, int kbits, uint32_t id_mask) } } - if (kbits == 2048) - keystore_add(KEYGEN_RSA2048, pub_der, publen, keyfile, id_mask); - else if (kbits == 3072) - keystore_add(KEYGEN_RSA3072, pub_der, publen, keyfile, id_mask); - else if (kbits == 4096) - keystore_add(KEYGEN_RSA4096, pub_der, publen, keyfile, id_mask); + keystore_add(ktype, pub_der, publen, keyfile, id_mask); } #define MAX_ECC_KEY_SIZE 66 @@ -1210,13 +1236,22 @@ static void key_generate(uint32_t ktype, const char *kfilename, uint32_t id_mask #ifndef NO_RSA case KEYGEN_RSA2048: - keygen_rsa(kfilename, 2048, id_mask); + keygen_rsa(kfilename, 2048, id_mask, KEYGEN_RSA2048); break; case KEYGEN_RSA3072: - keygen_rsa(kfilename, 3072, id_mask); + keygen_rsa(kfilename, 3072, id_mask, KEYGEN_RSA3072); break; case KEYGEN_RSA4096: - keygen_rsa(kfilename, 4096, id_mask); + keygen_rsa(kfilename, 4096, id_mask, KEYGEN_RSA4096); + break; + case KEYGEN_RSAPSS2048: + keygen_rsa(kfilename, 2048, id_mask, KEYGEN_RSAPSS2048); + break; + case KEYGEN_RSAPSS3072: + keygen_rsa(kfilename, 3072, id_mask, KEYGEN_RSAPSS3072); + break; + case KEYGEN_RSAPSS4096: + keygen_rsa(kfilename, 4096, id_mask, KEYGEN_RSAPSS4096); break; #endif @@ -1391,6 +1426,15 @@ int main(int argc, char** argv) else if (strcmp(argv[i], "--rsa4096") == 0) { keytype = KEYGEN_RSA4096; } + else if (strcmp(argv[i], "--rsapss2048") == 0) { + keytype = KEYGEN_RSAPSS2048; + } + else if (strcmp(argv[i], "--rsapss3072") == 0) { + keytype = KEYGEN_RSAPSS3072; + } + else if (strcmp(argv[i], "--rsapss4096") == 0) { + keytype = KEYGEN_RSAPSS4096; + } #if defined(WOLFSSL_HAVE_LMS) else if (strcmp(argv[i], "--lms") == 0) { keytype = KEYGEN_LMS; diff --git a/tools/keytools/sign.c b/tools/keytools/sign.c index 5109c9d9a2..28039838b5 100644 --- a/tools/keytools/sign.c +++ b/tools/keytools/sign.c @@ -193,6 +193,9 @@ static inline int fp_truncate(FILE *f, size_t len) #define SIGN_RSA2048 HDR_IMG_TYPE_AUTH_RSA2048 #define SIGN_RSA3072 HDR_IMG_TYPE_AUTH_RSA3072 #define SIGN_RSA4096 HDR_IMG_TYPE_AUTH_RSA4096 +#define SIGN_RSAPSS2048 HDR_IMG_TYPE_AUTH_RSAPSS2048 +#define SIGN_RSAPSS3072 HDR_IMG_TYPE_AUTH_RSAPSS3072 +#define SIGN_RSAPSS4096 HDR_IMG_TYPE_AUTH_RSAPSS4096 #define SIGN_ED448 HDR_IMG_TYPE_AUTH_ED448 #define SIGN_ECC384 HDR_IMG_TYPE_AUTH_ECC384 #define SIGN_ECC521 HDR_IMG_TYPE_AUTH_ECC521 @@ -756,6 +759,25 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, if (ret == 0) break; + FALL_THROUGH; /* we didn't solve the key, keep trying */ + case SIGN_RSAPSS2048: + ret = load_key_rsa(SIGN_RSAPSS2048, 256, KEYSTORE_PUBKEY_SIZE_RSA2048, 512, + key_buffer, key_buffer_sz, pubkey, pubkey_sz, secondary); + if (ret == 0) + break; + FALL_THROUGH; + case SIGN_RSAPSS3072: + ret = load_key_rsa(SIGN_RSAPSS3072, 384, KEYSTORE_PUBKEY_SIZE_RSA3072, 512, + key_buffer, key_buffer_sz, pubkey, pubkey_sz, secondary); + if (ret == 0) + break; + FALL_THROUGH; + case SIGN_RSAPSS4096: + ret = load_key_rsa(SIGN_RSAPSS4096, 512, KEYSTORE_PUBKEY_SIZE_RSA4096, 1024, + 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_LMS: ret = -1; @@ -1029,6 +1051,30 @@ static int sign_digest(int sign, int hash_algo, } } else + if (sign == SIGN_RSAPSS2048 || + sign == SIGN_RSAPSS3072 || + sign == SIGN_RSAPSS4096) + { + enum wc_HashType hash_type; + int mgf; + if (hash_algo == HASH_SHA256) { + hash_type = WC_HASH_TYPE_SHA256; + mgf = WC_MGF1SHA256; + } else if (hash_algo == HASH_SHA384) { + hash_type = WC_HASH_TYPE_SHA384; + mgf = WC_MGF1SHA384; + } else { + fprintf(stderr, "RSA-PSS requires SHA-256 or SHA-384\n"); + return -1; + } + ret = wc_RsaPSS_Sign(digest, digest_sz, signature, *signature_sz, + hash_type, mgf, &key.rsa, &rng); + if (ret > 0) { + *signature_sz = ret; + ret = 0; + } + } + else if (sign == SIGN_LMS) { const char *key_file = CMD.key_file; if (secondary) { @@ -2342,6 +2388,23 @@ static void set_signature_sizes(int secondary) CMD.header_sz = 1024; *sz = 512; } + else if (*sign == SIGN_RSAPSS2048) { + if (CMD.header_sz < 512) + CMD.header_sz = 512; + *sz = 256; + } + else if (*sign == SIGN_RSAPSS3072) { + 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_RSAPSS4096) { + if (CMD.header_sz < 1024) + CMD.header_sz = 1024; + *sz = 512; + } else if (*sign == SIGN_LMS) { int lms_ret = 0; word32 sig_sz = 0; @@ -2635,6 +2698,36 @@ int main(int argc, char** argv) sign_str = "RSA4096"; } } + else if (strcmp(argv[i], "--rsapss2048") == 0) { + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSAPSS2048; + secondary_sign_str = "RSAPSS2048"; + } else { + CMD.sign = SIGN_RSAPSS2048; + sign_str = "RSAPSS2048"; + } + } + else if (strcmp(argv[i], "--rsapss3072") == 0) { + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSAPSS3072; + secondary_sign_str = "RSAPSS3072"; + } else { + CMD.sign = SIGN_RSAPSS3072; + sign_str = "RSAPSS3072"; + } + } + else if (strcmp(argv[i], "--rsapss4096") == 0) { + if (CMD.sign != SIGN_AUTO) { + CMD.hybrid = 1; + CMD.secondary_sign = SIGN_RSAPSS4096; + secondary_sign_str = "RSAPSS4096"; + } else { + CMD.sign = SIGN_RSAPSS4096; + sign_str = "RSAPSS4096"; + } + } else if (strcmp(argv[i], "--lms") == 0) { if (CMD.sign != SIGN_AUTO) { CMD.hybrid = 1; @@ -3043,7 +3136,10 @@ int main(int argc, char** argv) } else if (CMD.sign == SIGN_RSA2048 || CMD.sign == SIGN_RSA3072 || - CMD.sign == SIGN_RSA4096) { + CMD.sign == SIGN_RSA4096 || + CMD.sign == SIGN_RSAPSS2048 || + CMD.sign == SIGN_RSAPSS3072 || + CMD.sign == SIGN_RSAPSS4096) { wc_FreeRsaKey(&key.rsa); } else if (CMD.sign == SIGN_LMS) { diff --git a/tools/keytools/user_settings.h b/tools/keytools/user_settings.h index 7c888d115c..cb7d8a3d8d 100644 --- a/tools/keytools/user_settings.h +++ b/tools/keytools/user_settings.h @@ -68,6 +68,7 @@ /* RSA */ #define HAVE_RSA #define WC_RSA_BLINDING +#define WC_RSA_PSS #define WOLFSSL_KEY_GEN /* Hashing */