Skip to content

Commit 1f72804

Browse files
bigbrettdanielinux
authored andcommitted
support rsa-pss in ARMORED mode
1 parent 65d84a2 commit 1f72804

2 files changed

Lines changed: 115 additions & 46 deletions

File tree

include/image.h

Lines changed: 102 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok(
382382
* double checking its return value contains a valid
383383
* len (>= WOLFBOOT_SHA_DIGEST_SIZE).
384384
*
385+
* Uses GAS local numeric labels (1f/1:) so the macro can be safely expanded
386+
* multiple times in the same function (e.g. RSA PKCS#1.5 + RSA-PSS paths).
385387
*/
386388
#define RSA_VERIFY_FN(ret,fn,...) \
387389
{ \
@@ -400,22 +402,22 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok(
400402
asm volatile("cmp r0, r2":::"cc"); \
401403
asm volatile("cmp r0, r2":::"cc"); \
402404
asm volatile("cmp r0, r2":::"cc"); \
403-
asm volatile("blt nope"); \
405+
asm volatile("blt 1f"); \
404406
asm volatile("cmp r0, r2":::"cc"); \
405407
asm volatile("cmp r0, r2":::"cc"); \
406408
asm volatile("cmp r0, r2":::"cc"); \
407-
asm volatile("blt nope"); \
409+
asm volatile("blt 1f"); \
408410
asm volatile("cmp r0, r2":::"cc"); \
409411
asm volatile("cmp r0, r2":::"cc"); \
410412
asm volatile("cmp r0, r2":::"cc"); \
411-
asm volatile("blt nope"); \
413+
asm volatile("blt 1f"); \
412414
asm volatile("cmp r0, r2":::"cc"); \
413415
asm volatile("cmp r0, r2":::"cc"); \
414416
asm volatile("cmp r0, r2":::"cc"); \
415-
asm volatile("blt nope"); \
417+
asm volatile("blt 1f"); \
416418
/* Return value is set here in case of success */ \
417419
ret = tmp_ret; \
418-
asm volatile("nope:"); \
420+
asm volatile("1:"); \
419421
asm volatile("nop"); \
420422
}
421423

@@ -424,12 +426,14 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok(
424426
*
425427
* Compare the digest twice, then confirm via
426428
* wolfBoot_image_confirm_signature_ok();
429+
*
430+
* Uses GAS local numeric labels (2f/2:) for safe multi-expansion.
427431
*/
428432
#define RSA_VERIFY_HASH(img,digest) \
429433
{ \
430434
volatile int compare_res; \
431435
if (!img || !digest) \
432-
asm volatile("b hnope"); \
436+
asm volatile("b 2f"); \
433437
/* Redundant set of r0=50*/ \
434438
asm volatile("mov r0, #50":::"r0"); \
435439
asm volatile("mov r0, #50":::"r0"); \
@@ -440,19 +444,19 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok(
440444
asm volatile("cmp r0, #0":::"cc"); \
441445
asm volatile("cmp r0, #0":::"cc"); \
442446
asm volatile("cmp r0, #0":::"cc"); \
443-
asm volatile("bne hnope":::"cc"); \
447+
asm volatile("bne 2f":::"cc"); \
444448
asm volatile("cmp r0, #0"); \
445449
asm volatile("cmp r0, #0"); \
446450
asm volatile("cmp r0, #0"); \
447-
asm volatile("bne hnope":::"cc"); \
451+
asm volatile("bne 2f":::"cc"); \
448452
asm volatile("cmp r0, #0":::"cc"); \
449453
asm volatile("cmp r0, #0":::"cc"); \
450454
asm volatile("cmp r0, #0":::"cc"); \
451-
asm volatile("bne hnope"); \
455+
asm volatile("bne 2f"); \
452456
asm volatile("cmp r0, #0":::"cc"); \
453457
asm volatile("cmp r0, #0":::"cc"); \
454458
asm volatile("cmp r0, #0":::"cc"); \
455-
asm volatile("bne hnope"); \
459+
asm volatile("bne 2f"); \
456460
/* Repeat comparison call */ \
457461
compare_res = image_CT_compare(digest, img->sha_hash, \
458462
WOLFBOOT_SHA_DIGEST_SIZE); \
@@ -461,22 +465,85 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok(
461465
asm volatile("cmp r0, #0":::"cc"); \
462466
asm volatile("cmp r0, #0":::"cc"); \
463467
asm volatile("cmp r0, #0":::"cc"); \
464-
asm volatile("bne hnope"); \
468+
asm volatile("bne 2f"); \
465469
asm volatile("cmp r0, #0":::"cc"); \
466470
asm volatile("cmp r0, #0":::"cc"); \
467471
asm volatile("cmp r0, #0":::"cc"); \
468-
asm volatile("bne hnope"); \
472+
asm volatile("bne 2f"); \
469473
asm volatile("cmp r0, #0":::"cc"); \
470474
asm volatile("cmp r0, #0":::"cc"); \
471475
asm volatile("cmp r0, #0":::"cc"); \
472-
asm volatile("bne hnope"); \
476+
asm volatile("bne 2f"); \
473477
asm volatile("cmp r0, #0":::"cc"); \
474478
asm volatile("cmp r0, #0":::"cc"); \
475479
asm volatile("cmp r0, #0":::"cc"); \
476-
asm volatile("bne hnope"); \
480+
asm volatile("bne 2f"); \
477481
/* Confirm that the signature is OK */ \
478482
wolfBoot_image_confirm_signature_ok(img); \
479-
asm volatile("hnope:"); \
483+
asm volatile("2:"); \
484+
asm volatile("nop"); \
485+
}
486+
487+
/**
488+
* Second part of RSA-PSS verification.
489+
*
490+
* Call wc_RsaPSS_CheckPadding twice, then confirm via
491+
* wolfBoot_image_confirm_signature_ok();
492+
*
493+
* Uses GAS local numeric labels (3f/3:) for safe multi-expansion.
494+
*/
495+
#define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \
496+
{ \
497+
volatile int pss_res; \
498+
if (!img || !pss_data) \
499+
asm volatile("b 3f"); \
500+
/* Redundant set of r0=50*/ \
501+
asm volatile("mov r0, #50":::"r0"); \
502+
asm volatile("mov r0, #50":::"r0"); \
503+
asm volatile("mov r0, #50":::"r0"); \
504+
pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
505+
pss_data, pss_data_sz, hash_type); \
506+
/* Redundant checks that ensure the function actually returned 0 */ \
507+
asm volatile("cmp r0, #0":::"cc"); \
508+
asm volatile("cmp r0, #0":::"cc"); \
509+
asm volatile("cmp r0, #0":::"cc"); \
510+
asm volatile("bne 3f":::"cc"); \
511+
asm volatile("cmp r0, #0"); \
512+
asm volatile("cmp r0, #0"); \
513+
asm volatile("cmp r0, #0"); \
514+
asm volatile("bne 3f":::"cc"); \
515+
asm volatile("cmp r0, #0":::"cc"); \
516+
asm volatile("cmp r0, #0":::"cc"); \
517+
asm volatile("cmp r0, #0":::"cc"); \
518+
asm volatile("bne 3f"); \
519+
asm volatile("cmp r0, #0":::"cc"); \
520+
asm volatile("cmp r0, #0":::"cc"); \
521+
asm volatile("cmp r0, #0":::"cc"); \
522+
asm volatile("bne 3f"); \
523+
/* Repeat wc_RsaPSS_CheckPadding call */ \
524+
pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
525+
pss_data, pss_data_sz, hash_type); \
526+
pss_res; \
527+
/* Redundant checks that ensure the function actually returned 0 */ \
528+
asm volatile("cmp r0, #0":::"cc"); \
529+
asm volatile("cmp r0, #0":::"cc"); \
530+
asm volatile("cmp r0, #0":::"cc"); \
531+
asm volatile("bne 3f"); \
532+
asm volatile("cmp r0, #0":::"cc"); \
533+
asm volatile("cmp r0, #0":::"cc"); \
534+
asm volatile("cmp r0, #0":::"cc"); \
535+
asm volatile("bne 3f"); \
536+
asm volatile("cmp r0, #0":::"cc"); \
537+
asm volatile("cmp r0, #0":::"cc"); \
538+
asm volatile("cmp r0, #0":::"cc"); \
539+
asm volatile("bne 3f"); \
540+
asm volatile("cmp r0, #0":::"cc"); \
541+
asm volatile("cmp r0, #0":::"cc"); \
542+
asm volatile("cmp r0, #0":::"cc"); \
543+
asm volatile("bne 3f"); \
544+
/* Confirm that the signature is OK */ \
545+
wolfBoot_image_confirm_signature_ok(img); \
546+
asm volatile("3:"); \
480547
asm volatile("nop"); \
481548
}
482549

@@ -489,6 +556,8 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok(
489556
* set the return value accordingly.
490557
*
491558
* Double check by reading the value in p_res from memory a few times.
559+
*
560+
* Uses GAS local numeric labels (4f/4:) for safe multi-expansion.
492561
*/
493562
#if defined(__GNUC__)
494563

@@ -503,63 +572,63 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok(
503572
asm volatile("cmp r0, #0":::"cc"); \
504573
asm volatile("cmp r0, #0":::"cc"); \
505574
asm volatile("cmp r0, #0":::"cc"); \
506-
asm volatile("bne nope"); \
575+
asm volatile("bne 4f"); \
507576
asm volatile("cmp r0, #0":::"cc"); \
508577
asm volatile("cmp r0, #0":::"cc"); \
509578
asm volatile("cmp r0, #0":::"cc"); \
510-
asm volatile("bne nope"); \
579+
asm volatile("bne 4f"); \
511580
asm volatile("cmp r0, #0":::"cc"); \
512581
asm volatile("cmp r0, #0":::"cc"); \
513582
asm volatile("cmp r0, #0":::"cc"); \
514-
asm volatile("bne nope"); \
583+
asm volatile("bne 4f"); \
515584
asm volatile("cmp r0, #0":::"cc"); \
516585
asm volatile("cmp r0, #0":::"cc"); \
517586
asm volatile("cmp r0, #0":::"cc"); \
518-
asm volatile("bne nope"); \
587+
asm volatile("bne 4f"); \
519588
/* Check that res = 1, a few times, reading the value from memory */ \
520589
asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
521590
asm volatile("cmp r2, #1":::"cc"); \
522591
asm volatile("cmp r2, #1":::"cc"); \
523592
asm volatile("cmp r2, #1":::"cc"); \
524-
asm volatile("bne nope"); \
593+
asm volatile("bne 4f"); \
525594
asm volatile("mvn r3, r2":::"r3"); \
526595
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
527596
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
528597
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
529-
asm volatile("bne nope"); \
598+
asm volatile("bne 4f"); \
530599
asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
531600
asm volatile("cmp r2, #1":::"cc"); \
532601
asm volatile("cmp r2, #1":::"cc"); \
533602
asm volatile("cmp r2, #1":::"cc"); \
534-
asm volatile("bne nope"); \
603+
asm volatile("bne 4f"); \
535604
asm volatile("mvn r3, r2":::"r3"); \
536605
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
537606
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
538607
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
539-
asm volatile("bne nope"); \
608+
asm volatile("bne 4f"); \
540609
asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
541610
asm volatile("cmp r2, #1":::"cc"); \
542611
asm volatile("cmp r2, #1":::"cc"); \
543612
asm volatile("cmp r2, #1":::"cc"); \
544-
asm volatile("bne nope"); \
613+
asm volatile("bne 4f"); \
545614
asm volatile("mvn r3, r2":::"r3"); \
546615
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
547616
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
548617
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
549-
asm volatile("bne nope"); \
618+
asm volatile("bne 4f"); \
550619
asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
551620
asm volatile("cmp r2, #1":::"cc"); \
552621
asm volatile("cmp r2, #1":::"cc"); \
553622
asm volatile("cmp r2, #1":::"cc"); \
554-
asm volatile("bne nope"); \
623+
asm volatile("bne 4f"); \
555624
asm volatile("mvn r3, r2":::"r3"); \
556625
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
557626
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
558627
asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
559-
asm volatile("bne nope"); \
628+
asm volatile("bne 4f"); \
560629
/* Confirm that the signature is OK */ \
561630
wolfBoot_image_confirm_signature_ok(img); \
562-
asm volatile("nope:"); \
631+
asm volatile("4:"); \
563632
asm volatile("nop") \
564633

565634
#elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__)
@@ -1249,6 +1318,11 @@ static void UNUSEDFUNCTION wolfBoot_image_clear_signature_ok(
12491318
if (image_CT_compare(img->sha_hash, digest, WOLFBOOT_SHA_DIGEST_SIZE) == 0) \
12501319
wolfBoot_image_confirm_signature_ok(img);
12511320

1321+
#define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \
1322+
if (wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
1323+
pss_data, pss_data_sz, hash_type) == 0) \
1324+
wolfBoot_image_confirm_signature_ok(img);
1325+
12521326
#define PART_SANITY_CHECK(p) \
12531327
if (((p)->hdr_ok != 1) || ((p)->sha_ok != 1) || ((p)->signature_ok != 1)) \
12541328
wolfBoot_panic()

src/image.c

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -601,34 +601,29 @@ static void wolfBoot_verify_signature_rsa_pss(uint8_t key_slot,
601601
return;
602602
}
603603

604-
/* wolfCrypt software RSA-PSS verify */
604+
/* wolfCrypt software RSA-PSS verify (two-step)
605+
*
606+
* Step 1 (RSA_VERIFY_FN): wc_RsaPSS_VerifyInline performs the RSA
607+
* operation and PSS unmasking, returning a pointer to the PSS data and
608+
* its length.
609+
*
610+
* Step 2 (RSA_PSS_VERIFY_HASH): wc_RsaPSS_CheckPadding verifies the PSS
611+
* padding against img->sha_hash. Returns 0 on success. Both steps are
612+
* armored when WOLFBOOT_ARMORED is enabled. */
605613
ret = wc_InitRsaKey(&rsa, NULL);
606614
if (ret == 0) {
607615
/* Import public key */
608616
ret = wc_RsaPublicKeyDecode((byte*)pubkey, &inOutIdx, &rsa, pubkey_sz);
609617
if (ret >= 0) {
610618
XMEMCPY(output, sig, RSA_IMAGE_SIGNATURE_SIZE);
611619
RSA_VERIFY_FN(ret,
612-
wc_RsaPSS_VerifyCheckInline, output, RSA_IMAGE_SIGNATURE_SIZE,
613-
&digest_out, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE,
614-
hash_type, mgf, &rsa);
620+
wc_RsaPSS_VerifyInline, output, RSA_IMAGE_SIGNATURE_SIZE,
621+
&digest_out, hash_type, mgf, &rsa);
615622
}
616623
}
617624
wc_FreeRsaKey(&rsa);
618-
/* wc_RsaPSS_VerifyCheckInline returns the PSS-verified data length on
619-
* success (>= digest size), or a negative error code on failure.
620-
* The hash comparison is performed internally by the function.
621-
*
622-
* Note: uses '>=' rather than '==' because PSS verify returns the digest
623-
* size on success, unlike PKCS#1 v1.5 which returns exact decoded length.
624-
*
625-
* ARMORED limitation: the PKCS#1 v1.5 path uses both RSA_VERIFY_FN and
626-
* RSA_VERIFY_HASH armored macros (two hardened gates), but PSS only uses
627-
* RSA_VERIFY_FN because wc_RsaPSS_VerifyCheckInline performs the hash
628-
* comparison internally. The branch below is not armored. Full armored
629-
* hardening for PSS would require a new macro or restructuring. */
630-
if (ret >= WOLFBOOT_SHA_DIGEST_SIZE && img) {
631-
wolfBoot_image_confirm_signature_ok(img);
625+
if (ret >= WOLFBOOT_SHA_DIGEST_SIZE && img && digest_out) {
626+
RSA_PSS_VERIFY_HASH(img, digest_out, ret, hash_type);
632627
}
633628
}
634629

0 commit comments

Comments
 (0)