@@ -79,6 +79,10 @@ static int ecc_init_fail = 1;
7979static int ecc_import_fail = 1 ;
8080
8181static int verify_called = 0 ;
82+ static int verify_hash_count = 0 ;
83+ static int verify_capture_hashes = 0 ;
84+ static int verify_reject_hash_mismatch = 0 ;
85+ static uint8_t verify_hashes [2 ][WOLFBOOT_SHA_DIGEST_SIZE ];
8286
8387static int find_header_fail = 0 ;
8488static int find_header_called = 0 ;
@@ -263,6 +267,48 @@ static void patch_image_type_part(uint8_t *img, uint32_t img_len, uint16_t part)
263267 ptr [0 ] = (uint8_t )(type & 0xFF );
264268 ptr [1 ] = (uint8_t )(type >> 8 );
265269}
270+
271+ static void patch_stored_hash (uint8_t * img , uint32_t img_len )
272+ {
273+ struct wolfBoot_image tmp_img ;
274+ uint8_t hash [WOLFBOOT_SHA_DIGEST_SIZE ];
275+ uint8_t * stored_sha = NULL ;
276+ uint16_t stored_sha_len ;
277+ int saved_find_header_mocked = find_header_mocked ;
278+
279+ (void )img_len ;
280+ find_header_mocked = 0 ;
281+ memset (& tmp_img , 0 , sizeof (tmp_img ));
282+ tmp_img .part = PART_BOOT ;
283+ tmp_img .hdr = img ;
284+ tmp_img .fw_base = img + IMAGE_HEADER_SIZE ;
285+ tmp_img .fw_size = wolfBoot_image_size (img );
286+
287+ ck_assert_int_eq (image_hash (& tmp_img , hash ), 0 );
288+ stored_sha_len = _find_header (img + IMAGE_HEADER_OFFSET , WOLFBOOT_SHA_HDR ,
289+ & stored_sha );
290+ ck_assert_uint_eq (stored_sha_len , WOLFBOOT_SHA_DIGEST_SIZE );
291+ memcpy (stored_sha , hash , WOLFBOOT_SHA_DIGEST_SIZE );
292+ find_header_mocked = saved_find_header_mocked ;
293+ }
294+
295+ static void append_header_tag (uint8_t * img , uint32_t img_len , uint32_t * idx ,
296+ uint16_t type , uint16_t len , const uint8_t * data )
297+ {
298+ ck_assert_ptr_nonnull (img );
299+ ck_assert_ptr_nonnull (idx );
300+ ck_assert_ptr_nonnull (data );
301+ ck_assert_uint_le (* idx + 4U + len , img_len );
302+ ck_assert_uint_le (* idx + 4U + len , IMAGE_HEADER_SIZE );
303+
304+ img [* idx ] = (uint8_t )(type & 0xFF );
305+ img [* idx + 1U ] = (uint8_t )(type >> 8 );
306+ img [* idx + 2U ] = (uint8_t )(len & 0xFF );
307+ img [* idx + 3U ] = (uint8_t )(len >> 8 );
308+ memcpy (img + * idx + 4U , data , len );
309+ * idx += 4U + len ;
310+ }
311+
266312static const unsigned int test_img_len = 275 ;
267313
268314
@@ -293,6 +339,37 @@ unsigned char test_img_v123_signed_bin[] = {
293339};
294340unsigned int test_img_v123_signed_bin_len = 275 ;
295341
342+ #if defined(UNIT_IMAGE_HYBRID_ONLY )
343+ static void build_hybrid_test_image (uint8_t * img , uint32_t img_len )
344+ {
345+ uint8_t secondary_pubkey_hint [WOLFBOOT_SHA_DIGEST_SIZE ];
346+ uint8_t secondary_signature [ECC_IMAGE_SIGNATURE_SIZE ];
347+ uint32_t idx = 256U ;
348+ uint32_t fixture_payload_len ;
349+
350+ ck_assert_uint_ge (IMAGE_HEADER_SIZE , 512U );
351+ ck_assert_uint_ge (img_len , IMAGE_HEADER_SIZE +
352+ wolfBoot_image_size (test_img_v123_signed_bin ));
353+
354+ memset (img , 0xFF , img_len );
355+ memcpy (img , test_img_v123_signed_bin , 256U );
356+
357+ fixture_payload_len = test_img_v123_signed_bin_len - 256U ;
358+ memcpy (img + IMAGE_HEADER_SIZE , test_img_v123_signed_bin + 256U ,
359+ fixture_payload_len );
360+
361+ patch_image_type_auth (img , img_len );
362+ patch_pubkey_hint_slot (img , img_len , 0 );
363+
364+ key_hash (2 , secondary_pubkey_hint );
365+ memset (secondary_signature , 0 , sizeof (secondary_signature ));
366+ append_header_tag (img , img_len , & idx , HDR_SECONDARY_PUBKEY ,
367+ sizeof (secondary_pubkey_hint ), secondary_pubkey_hint );
368+ append_header_tag (img , img_len , & idx , HDR_SECONDARY_SIGNATURE ,
369+ sizeof (secondary_signature ), secondary_signature );
370+ }
371+ #endif
372+
296373
297374static uint16_t _find_header (uint8_t * haystack , uint16_t type , uint8_t * * ptr )
298375{
@@ -388,8 +465,21 @@ int wc_ecc_import_unsigned(ecc_key* key, const byte* qx, const byte* qy,
388465int wc_ecc_verify_hash_ex (mp_int * r , mp_int * s , const byte * hash ,
389466 word32 hashlen , int * res , ecc_key * key )
390467{
468+ int call_idx = verify_hash_count ;
469+ int valid_hash = (hash != NULL && hashlen == WOLFBOOT_SHA_DIGEST_SIZE );
470+
471+ if (verify_capture_hashes && call_idx < 2 && valid_hash ) {
472+ memcpy (verify_hashes [call_idx ], hash , WOLFBOOT_SHA_DIGEST_SIZE );
473+ }
474+ verify_hash_count ++ ;
391475 verify_called ++ ;
392- * res = 1 ;
476+ if (verify_capture_hashes && verify_reject_hash_mismatch &&
477+ call_idx > 0 && valid_hash &&
478+ memcmp (hash , verify_hashes [0 ], WOLFBOOT_SHA_DIGEST_SIZE ) != 0 ) {
479+ * res = 0 ;
480+ } else {
481+ * res = 1 ;
482+ }
393483 return 0 ;
394484}
395485#endif
@@ -685,6 +775,9 @@ START_TEST(test_verify_authenticity)
685775 ext_flash_erase (0 , 2 * WOLFBOOT_SECTOR_SIZE );
686776 ext_flash_write (0 , test_img_v123_signed_bin ,
687777 test_img_v123_signed_bin_len );
778+ memset (& test_img , 0 , sizeof (struct wolfBoot_image ));
779+ ret = wolfBoot_open_image (& test_img , PART_UPDATE );
780+ ck_assert_int_eq (ret , 0 );
688781 test_img .signature_ok = 1 ; /* mock for VERIFY_FN */
689782 ret = wolfBoot_verify_authenticity (& test_img );
690783 ck_assert_int_eq (ret , 0 );
@@ -772,6 +865,7 @@ START_TEST(test_verify_authenticity_allows_permitted_key_mask)
772865 patch_image_type_auth (buf , sizeof (buf ));
773866 patch_pubkey_hint_slot (buf , sizeof (buf ), 1 );
774867 patch_image_type_part (buf , sizeof (buf ), HDR_IMG_TYPE_APP );
868+ patch_stored_hash (buf , sizeof (buf ));
775869
776870 find_header_mocked = 0 ;
777871 find_header_fail = 0 ;
@@ -782,12 +876,59 @@ START_TEST(test_verify_authenticity_allows_permitted_key_mask)
782876 ext_flash_write (0 , buf , sizeof (buf ));
783877
784878 memset (& test_img , 0 , sizeof (struct wolfBoot_image ));
785- test_img .part = PART_UPDATE ;
879+ ret = wolfBoot_open_image (& test_img , PART_UPDATE );
880+ ck_assert_int_eq (ret , 0 );
786881 test_img .signature_ok = 1 ;
787882 ret = wolfBoot_verify_authenticity (& test_img );
788883 ck_assert_int_eq (ret , 0 );
789884}
790885END_TEST
886+
887+ #if defined(UNIT_IMAGE_HYBRID_ONLY ) && defined(SIGN_HYBRID ) && \
888+ defined(WOLFBOOT_SIGN_SECONDARY_ECC256 )
889+ START_TEST (test_verify_authenticity_hybrid_direct_call_uses_verified_sha )
890+ {
891+ struct wolfBoot_image test_img ;
892+ uint8_t * stored_sha = NULL ;
893+ uint16_t stored_sha_len ;
894+ uint32_t image_len ;
895+ uint8_t image [IMAGE_HEADER_SIZE + 123U ];
896+ int ret ;
897+
898+ find_header_mocked = 0 ;
899+ find_header_fail = 0 ;
900+ hdr_cpy_done = 0 ;
901+ ecc_import_fail = 0 ;
902+ ecc_init_fail = 0 ;
903+ verify_hash_count = 0 ;
904+ verify_capture_hashes = 1 ;
905+ verify_reject_hash_mismatch = 1 ;
906+ verify_called = 0 ;
907+
908+ build_hybrid_test_image (image , sizeof (image ));
909+ image_len = IMAGE_HEADER_SIZE + wolfBoot_image_size (image );
910+
911+ ext_flash_erase (WOLFBOOT_PARTITION_UPDATE_ADDRESS , WOLFBOOT_SECTOR_SIZE );
912+ ext_flash_write (WOLFBOOT_PARTITION_UPDATE_ADDRESS , image , image_len );
913+
914+ ret = wolfBoot_open_image (& test_img , PART_UPDATE );
915+ ck_assert_int_eq (ret , 0 );
916+ ck_assert_ptr_null (test_img .sha_hash );
917+ ck_assert_uint_eq (test_img .sha_ok , 0 );
918+
919+ ret = wolfBoot_verify_authenticity (& test_img );
920+ ck_assert_int_eq (ret , 0 );
921+
922+ stored_sha_len = get_header (& test_img , WOLFBOOT_SHA_HDR , & stored_sha );
923+ ck_assert_uint_eq (stored_sha_len , WOLFBOOT_SHA_DIGEST_SIZE );
924+ ck_assert_uint_eq (test_img .sha_ok , 1 );
925+ ck_assert_ptr_eq (test_img .sha_hash , stored_sha );
926+ ck_assert_int_eq (verify_hash_count , 2 );
927+ ck_assert_mem_eq (verify_hashes [0 ], verify_hashes [1 ],
928+ WOLFBOOT_SHA_DIGEST_SIZE );
929+ }
930+ END_TEST
931+ #endif
791932#endif
792933
793934#ifdef WOLFBOOT_FIXED_PARTITIONS
@@ -938,6 +1079,15 @@ Suite *wolfboot_suite(void)
9381079 return s ;
9391080#endif
9401081
1082+ #ifdef UNIT_IMAGE_HYBRID_ONLY
1083+ TCase * tcase_hybrid_auth = tcase_create ("hybrid_auth" );
1084+ tcase_set_timeout (tcase_hybrid_auth , 20 );
1085+ tcase_add_test (tcase_hybrid_auth ,
1086+ test_verify_authenticity_hybrid_direct_call_uses_verified_sha );
1087+ suite_add_tcase (s , tcase_hybrid_auth );
1088+ return s ;
1089+ #endif
1090+
9411091#if defined(WOLFBOOT_SIGN_ECC256 )
9421092 TCase * tcase_verify_signature = tcase_create ("verify_signature" );
9431093 tcase_set_timeout (tcase_verify_signature , 20 );
0 commit comments