4848#include <delta.h>
4949
5050#include "wolfboot/version.h"
51+ #include "wolfboot/wolfboot.h"
5152
5253#ifdef DEBUG_SIGNTOOL
5354#define DEBUG_PRINT (...) fprintf(stderr, __VA_ARGS__)
@@ -176,6 +177,7 @@ static inline int fp_truncate(FILE *f, size_t len)
176177
177178#define HDR_IMG_DELTA_BASE 0x05
178179#define HDR_IMG_DELTA_SIZE 0x06
180+ #define HDR_IMG_DELTA_BASE_HASH 0x07
179181#define HDR_IMG_DELTA_INVERSE 0x15
180182#define HDR_IMG_DELTA_INVERSE_SIZE 0x16
181183
@@ -289,6 +291,7 @@ struct cmd_options {
289291 const char * policy_file ;
290292 const char * encrypt_key_file ;
291293 const char * delta_base_file ;
294+ int no_base_sha ;
292295 char output_image_file [PATH_MAX ];
293296 char output_diff_file [PATH_MAX ];
294297 char output_encrypted_image_file [PATH_MAX ];
@@ -316,6 +319,57 @@ static struct cmd_options CMD = {
316319 .hybrid = 0
317320};
318321
322+ static uint16_t sign_tool_find_header (uint8_t * haystack , uint16_t type , uint8_t * * ptr )
323+ {
324+ uint8_t * p = haystack ;
325+ uint16_t len , htype ;
326+ const volatile uint8_t * max_p = (haystack - IMAGE_HEADER_OFFSET ) +
327+ IMAGE_HEADER_SIZE ;
328+ * ptr = NULL ;
329+ if (p > max_p ) {
330+ fprintf (stderr , "Illegal address (too high)\n" );
331+ return 0 ;
332+ }
333+ while ((p + 4 ) < max_p ) {
334+ htype = p [0 ] | (p [1 ] << 8 );
335+ if (htype == 0 ) {
336+ fprintf (stderr , "Explicit end of options reached\n" );
337+ break ;
338+ }
339+ /* skip unaligned half-words and padding bytes */
340+ if ((p [0 ] == HDR_PADDING ) || ((((size_t )p ) & 0x01 ) != 0 )) {
341+ p ++ ;
342+ continue ;
343+ }
344+
345+ len = p [2 ] | (p [3 ] << 8 );
346+ /* check len */
347+ if ((4 + len ) > (uint16_t )(IMAGE_HEADER_SIZE - IMAGE_HEADER_OFFSET )) {
348+ fprintf (stderr , "This field is too large (bigger than the space available "
349+ "in the current header)\n" );
350+ //fprintf(stderr, "%d %d %d\n", len, IMAGE_HEADER_SIZE, IMAGE_HEADER_OFFSET);
351+ break ;
352+ }
353+ /* check max pointer */
354+ if (p + 4 + len > max_p ) {
355+ fprintf (stderr , "This field is too large and would overflow the image "
356+ "header\n" );
357+ break ;
358+ }
359+
360+ /* skip header [type|len] */
361+ p += 4 ;
362+
363+ if (htype == type ) {
364+ /* found, return pointer to data portion */
365+ * ptr = p ;
366+ return len ;
367+ }
368+ p += len ;
369+ }
370+ return 0 ;
371+ }
372+
319373static int load_key_ecc (int sign_type , uint32_t curve_sz , int curve_id ,
320374 int header_sz ,
321375 uint8_t * * key_buffer , uint32_t * key_buffer_sz ,
@@ -1063,7 +1117,8 @@ static int sign_digest(int sign, int hash_algo,
10631117static int make_header_ex (int is_diff , uint8_t * pubkey , uint32_t pubkey_sz ,
10641118 const char * image_file , const char * outfile ,
10651119 uint32_t delta_base_version , uint32_t patch_len , uint32_t patch_inv_off ,
1066- uint32_t patch_inv_len , const uint8_t * secondary_key , uint32_t secondary_key_sz )
1120+ uint32_t patch_inv_len , const uint8_t * secondary_key , uint32_t secondary_key_sz ,
1121+ uint8_t * base_hash , uint32_t base_hash_sz )
10671122{
10681123 uint32_t header_idx ;
10691124 uint8_t * header ;
@@ -1141,12 +1196,42 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
11411196 & patch_len );
11421197
11431198 /* Append pad bytes, so fields are 4-byte aligned */
1144- while ((header_idx % 4 ) != 0 )
1145- header_idx ++ ;
1199+ ALIGN_4 (header_idx );
11461200 header_append_tag (header , & header_idx , HDR_IMG_DELTA_INVERSE , 4 ,
11471201 & patch_inv_off );
11481202 header_append_tag (header , & header_idx , HDR_IMG_DELTA_INVERSE_SIZE , 4 ,
11491203 & patch_inv_len );
1204+
1205+ if (!CMD .no_base_sha ) {
1206+ /* Append pad bytes, so base hash is 8-byte aligned */
1207+ ALIGN_8 (header_idx );
1208+ if (!base_hash ) {
1209+ fprintf (stderr , "Base hash for delta image not found.\n" );
1210+ exit (1 );
1211+ }
1212+ if (CMD .hash_algo == HASH_SHA256 ) {
1213+ if (base_hash_sz != HDR_SHA256_LEN ) {
1214+ fprintf (stderr , "Invalid base hash size for SHA256.\n" );
1215+ exit (1 );
1216+ }
1217+ header_append_tag (header , & header_idx , HDR_IMG_DELTA_BASE_HASH ,
1218+ HDR_SHA256_LEN , base_hash );
1219+ } else if (CMD .hash_algo == HASH_SHA384 ) {
1220+ if (base_hash_sz != HDR_SHA384_LEN ) {
1221+ fprintf (stderr , "Invalid base hash size for SHA384.\n" );
1222+ exit (1 );
1223+ }
1224+ header_append_tag (header , & header_idx , HDR_IMG_DELTA_BASE_HASH ,
1225+ HDR_SHA384_LEN , base_hash );
1226+ } else if (CMD .hash_algo == HASH_SHA3 ) {
1227+ if (base_hash_sz != HDR_SHA3_384_LEN ) {
1228+ fprintf (stderr , "Invalid base hash size for SHA3-384.\n" );
1229+ exit (1 );
1230+ }
1231+ header_append_tag (header , & header_idx , HDR_IMG_DELTA_BASE_HASH ,
1232+ HDR_SHA3_384_LEN , base_hash );
1233+ }
1234+ }
11501235 }
11511236
11521237 /* Add custom TLVs */
@@ -1690,26 +1775,27 @@ static int make_header(uint8_t *pubkey, uint32_t pubkey_sz,
16901775 const char * image_file , const char * outfile )
16911776{
16921777 return make_header_ex (0 , pubkey , pubkey_sz , image_file , outfile , 0 , 0 , 0 , 0 ,
1693- NULL , 0 );
1778+ NULL , 0 , NULL , 0 );
16941779}
16951780
16961781static int make_header_delta (uint8_t * pubkey , uint32_t pubkey_sz ,
16971782 const char * image_file , const char * outfile ,
16981783 uint32_t delta_base_version , uint32_t patch_len ,
1699- uint32_t patch_inv_off , uint32_t patch_inv_len )
1784+ uint32_t patch_inv_off , uint32_t patch_inv_len ,
1785+ uint8_t * base_hash , uint32_t base_hash_sz )
17001786{
17011787 return make_header_ex (1 , pubkey , pubkey_sz , image_file , outfile ,
17021788 delta_base_version , patch_len ,
17031789 patch_inv_off , patch_inv_len ,
1704- NULL , 0 );
1790+ NULL , 0 , base_hash , base_hash_sz );
17051791}
17061792
17071793static int make_hybrid_header (uint8_t * pubkey , uint32_t pubkey_sz ,
17081794 const char * image_file , const char * outfile ,
17091795 const uint8_t * secondary_key , uint32_t secondary_key_sz )
17101796{
17111797 return make_header_ex (0 , pubkey , pubkey_sz , image_file , outfile , 0 , 0 , 0 , 0 ,
1712- secondary_key , secondary_key_sz );
1798+ secondary_key , secondary_key_sz , NULL , 0 );
17131799}
17141800
17151801static int base_diff (const char * f_base , uint8_t * pubkey , uint32_t pubkey_sz , int padding )
@@ -1734,6 +1820,8 @@ static int base_diff(const char *f_base, uint8_t *pubkey, uint32_t pubkey_sz, in
17341820 WB_DIFF_CTX diff_ctx ;
17351821 int ret = -1 ;
17361822 int io_sz ;
1823+ uint8_t * base_hash = NULL ;
1824+ uint32_t base_hash_sz = 0 ;
17371825
17381826 /* Get source file size */
17391827 if (stat (f_base , & st ) < 0 ) {
@@ -1790,14 +1878,21 @@ static int base_diff(const char *f_base, uint8_t *pubkey, uint32_t pubkey_sz, in
17901878 delta_base_version = (uint32_t )(retval & 0xFFFFFFFF );
17911879 }
17921880 }
1793-
17941881 if (delta_base_version == 0 ) {
17951882 printf ("Could not read firmware version from base file %s\n" , f_base );
17961883 goto cleanup ;
17971884 } else {
17981885 printf ("Delta base version: %u\n" , delta_base_version );
17991886 }
18001887
1888+ /* Retrieve the hash digest of the base image */
1889+ if (CMD .hash_algo == HASH_SHA256 )
1890+ base_hash_sz = sign_tool_find_header (base + 8 , HDR_SHA256 , & base_hash );
1891+ else if (CMD .hash_algo == HASH_SHA384 )
1892+ base_hash_sz = sign_tool_find_header (base + 8 , HDR_SHA384 , & base_hash );
1893+ else if (CMD .hash_algo == HASH_SHA3 )
1894+ base_hash_sz = sign_tool_find_header (base + 8 , HDR_SHA3_384 , & base_hash );
1895+
18011896#if HAVE_MMAP
18021897 /* Open second image file */
18031898 fd2 = open (CMD .output_image_file , O_RDONLY );
@@ -1952,7 +2047,7 @@ static int base_diff(const char *f_base, uint8_t *pubkey, uint32_t pubkey_sz, in
19522047 /* Create delta file, with header, from the resulting patch */
19532048
19542049 ret = make_header_delta (pubkey , pubkey_sz , wolfboot_delta_file , CMD .output_diff_file ,
1955- delta_base_version , patch_sz , patch_inv_off , patch_inv_sz );
2050+ delta_base_version , patch_sz , patch_inv_off , patch_inv_sz , base_hash , base_hash_sz );
19562051
19572052cleanup :
19582053 /* Unlink output file */
@@ -2398,6 +2493,8 @@ int main(int argc, char** argv)
23982493 else if (strcmp (argv [i ], "--delta" ) == 0 ) {
23992494 CMD .delta = 1 ;
24002495 CMD .delta_base_file = argv [++ i ];
2496+ } else if (strcmp (argv [i ], "--no-base-sha" ) == 0 ) {
2497+ CMD .no_base_sha = 1 ;
24012498 }
24022499 else if (strcmp (argv [i ], "--no-ts" ) == 0 ) {
24032500 CMD .no_ts = 1 ;
0 commit comments