@@ -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
@@ -648,6 +738,7 @@ START_TEST(test_headers)
648738}
649739
650740#if defined(WOLFBOOT_SIGN_ECC256 )
741+ #ifdef WOLFBOOT_FIXED_PARTITIONS
651742START_TEST (test_verify_authenticity )
652743{
653744 struct wolfBoot_image test_img ;
@@ -685,12 +776,16 @@ START_TEST(test_verify_authenticity)
685776 ext_flash_erase (0 , 2 * WOLFBOOT_SECTOR_SIZE );
686777 ext_flash_write (0 , test_img_v123_signed_bin ,
687778 test_img_v123_signed_bin_len );
779+ memset (& test_img , 0 , sizeof (struct wolfBoot_image ));
780+ ret = wolfBoot_open_image (& test_img , PART_UPDATE );
781+ ck_assert_int_eq (ret , 0 );
688782 test_img .signature_ok = 1 ; /* mock for VERIFY_FN */
689783 ret = wolfBoot_verify_authenticity (& test_img );
690784 ck_assert_int_eq (ret , 0 );
691785
692786}
693787END_TEST
788+ #endif /* WOLFBOOT_FIXED_PARTITIONS */
694789
695790START_TEST (test_verify_authenticity_bad_siglen )
696791{
@@ -762,6 +857,7 @@ START_TEST(test_verify_authenticity_rejects_disallowed_key_mask)
762857}
763858END_TEST
764859
860+ #ifdef WOLFBOOT_FIXED_PARTITIONS
765861START_TEST (test_verify_authenticity_allows_permitted_key_mask )
766862{
767863 struct wolfBoot_image test_img ;
@@ -772,6 +868,7 @@ START_TEST(test_verify_authenticity_allows_permitted_key_mask)
772868 patch_image_type_auth (buf , sizeof (buf ));
773869 patch_pubkey_hint_slot (buf , sizeof (buf ), 1 );
774870 patch_image_type_part (buf , sizeof (buf ), HDR_IMG_TYPE_APP );
871+ patch_stored_hash (buf , sizeof (buf ));
775872
776873 find_header_mocked = 0 ;
777874 find_header_fail = 0 ;
@@ -782,12 +879,60 @@ START_TEST(test_verify_authenticity_allows_permitted_key_mask)
782879 ext_flash_write (0 , buf , sizeof (buf ));
783880
784881 memset (& test_img , 0 , sizeof (struct wolfBoot_image ));
785- test_img .part = PART_UPDATE ;
882+ ret = wolfBoot_open_image (& test_img , PART_UPDATE );
883+ ck_assert_int_eq (ret , 0 );
786884 test_img .signature_ok = 1 ;
787885 ret = wolfBoot_verify_authenticity (& test_img );
788886 ck_assert_int_eq (ret , 0 );
789887}
790888END_TEST
889+ #endif /* WOLFBOOT_FIXED_PARTITIONS */
890+
891+ #if defined(UNIT_IMAGE_HYBRID_ONLY ) && defined(SIGN_HYBRID ) && \
892+ defined(WOLFBOOT_SIGN_SECONDARY_ECC256 )
893+ START_TEST (test_verify_authenticity_hybrid_direct_call_uses_verified_sha )
894+ {
895+ struct wolfBoot_image test_img ;
896+ uint8_t * stored_sha = NULL ;
897+ uint16_t stored_sha_len ;
898+ uint32_t image_len ;
899+ uint8_t image [IMAGE_HEADER_SIZE + 123U ];
900+ int ret ;
901+
902+ find_header_mocked = 0 ;
903+ find_header_fail = 0 ;
904+ hdr_cpy_done = 0 ;
905+ ecc_import_fail = 0 ;
906+ ecc_init_fail = 0 ;
907+ verify_hash_count = 0 ;
908+ verify_capture_hashes = 1 ;
909+ verify_reject_hash_mismatch = 1 ;
910+ verify_called = 0 ;
911+
912+ build_hybrid_test_image (image , sizeof (image ));
913+ image_len = IMAGE_HEADER_SIZE + wolfBoot_image_size (image );
914+
915+ ext_flash_erase (WOLFBOOT_PARTITION_UPDATE_ADDRESS , WOLFBOOT_SECTOR_SIZE );
916+ ext_flash_write (WOLFBOOT_PARTITION_UPDATE_ADDRESS , image , image_len );
917+
918+ ret = wolfBoot_open_image (& test_img , PART_UPDATE );
919+ ck_assert_int_eq (ret , 0 );
920+ ck_assert_ptr_null (test_img .sha_hash );
921+ ck_assert_uint_eq (test_img .sha_ok , 0 );
922+
923+ ret = wolfBoot_verify_authenticity (& test_img );
924+ ck_assert_int_eq (ret , 0 );
925+
926+ stored_sha_len = get_header (& test_img , WOLFBOOT_SHA_HDR , & stored_sha );
927+ ck_assert_uint_eq (stored_sha_len , WOLFBOOT_SHA_DIGEST_SIZE );
928+ ck_assert_uint_eq (test_img .sha_ok , 1 );
929+ ck_assert_ptr_eq (test_img .sha_hash , stored_sha );
930+ ck_assert_int_eq (verify_hash_count , 2 );
931+ ck_assert_mem_eq (verify_hashes [0 ], verify_hashes [1 ],
932+ WOLFBOOT_SHA_DIGEST_SIZE );
933+ }
934+ END_TEST
935+ #endif
791936#endif
792937
793938#ifdef WOLFBOOT_FIXED_PARTITIONS
@@ -938,6 +1083,15 @@ Suite *wolfboot_suite(void)
9381083 return s ;
9391084#endif
9401085
1086+ #ifdef UNIT_IMAGE_HYBRID_ONLY
1087+ TCase * tcase_hybrid_auth = tcase_create ("hybrid_auth" );
1088+ tcase_set_timeout (tcase_hybrid_auth , 20 );
1089+ tcase_add_test (tcase_hybrid_auth ,
1090+ test_verify_authenticity_hybrid_direct_call_uses_verified_sha );
1091+ suite_add_tcase (s , tcase_hybrid_auth );
1092+ return s ;
1093+ #endif
1094+
9411095#if defined(WOLFBOOT_SIGN_ECC256 )
9421096 TCase * tcase_verify_signature = tcase_create ("verify_signature" );
9431097 tcase_set_timeout (tcase_verify_signature , 20 );
@@ -960,14 +1114,18 @@ Suite *wolfboot_suite(void)
9601114#if defined(WOLFBOOT_SIGN_ECC256 )
9611115 TCase * tcase_verify_authenticity = tcase_create ("verify_authenticity" );
9621116 tcase_set_timeout (tcase_verify_authenticity , 20 );
1117+ #ifdef WOLFBOOT_FIXED_PARTITIONS
9631118 tcase_add_test (tcase_verify_authenticity , test_verify_authenticity );
1119+ #endif /* WOLFBOOT_FIXED_PARTITIONS */
9641120 tcase_add_test (tcase_verify_authenticity , test_verify_authenticity_bad_siglen );
9651121 tcase_add_test (tcase_verify_authenticity ,
9661122 test_verify_authenticity_rejects_mismatched_auth_type );
9671123 tcase_add_test (tcase_verify_authenticity ,
9681124 test_verify_authenticity_rejects_disallowed_key_mask );
1125+ #ifdef WOLFBOOT_FIXED_PARTITIONS
9691126 tcase_add_test (tcase_verify_authenticity ,
9701127 test_verify_authenticity_allows_permitted_key_mask );
1128+ #endif /* WOLFBOOT_FIXED_PARTITIONS */
9711129 suite_add_tcase (s , tcase_verify_authenticity );
9721130#endif
9731131
0 commit comments