4040#endif
4141#endif /* WOLFBOOT_GZIP */
4242
43+ /* Default upper bound on a single FIT subimage's decompressed size.
44+ * The outer wolfBoot signature already authenticates the FIT, but a
45+ * concrete cap defends against a malformed-but-signed FIT scribbling
46+ * across unrelated memory. Override per target via:
47+ * CFLAGS+=-DWOLFBOOT_FIT_MAX_DECOMP=...
48+ */
49+ #ifndef WOLFBOOT_FIT_MAX_DECOMP
50+ #define WOLFBOOT_FIT_MAX_DECOMP (256U * 1024U * 1024U)
51+ #endif
52+
4353uint32_t cpu_to_fdt32 (uint32_t x )
4454{
4555#ifdef BIG_ENDIAN_ORDER
@@ -911,6 +921,9 @@ static int fit_verify_hash(const void *fdt, int img_off,
911921 int hash_off , len = 0 ;
912922 const char * algo = NULL ;
913923 const uint8_t * value = NULL ;
924+ #if defined(WOLFBOOT_HASH_SHA256 ) || defined(WOLFBOOT_HASH_SHA384 )
925+ int did_init = 0 ;
926+ #endif
914927#ifdef WOLFBOOT_HASH_SHA256
915928 wc_Sha256 sha256_ctx ;
916929 uint8_t sha256_digest [WC_SHA256_DIGEST_SIZE ];
@@ -950,14 +963,20 @@ static int fit_verify_hash(const void *fdt, int img_off,
950963 }
951964 if (ret == 0 ) {
952965 ret = wc_InitSha256 (& sha256_ctx );
966+ if (ret == 0 ) {
967+ did_init = 1 ;
968+ }
953969 }
954970 if (ret == 0 ) {
955971 ret = wc_Sha256Update (& sha256_ctx , data , (word32 )data_len );
956972 }
957973 if (ret == 0 ) {
958974 ret = wc_Sha256Final (& sha256_ctx , sha256_digest );
959975 }
960- wc_Sha256Free (& sha256_ctx );
976+ if (did_init ) {
977+ wc_Sha256Free (& sha256_ctx );
978+ did_init = 0 ;
979+ }
961980 if (ret != 0 ) {
962981 wolfBoot_printf ("FIT hash-1 (sha256): wc_Sha256 failed rc=%d\n" ,
963982 ret );
@@ -982,14 +1001,20 @@ static int fit_verify_hash(const void *fdt, int img_off,
9821001 }
9831002 if (ret == 0 ) {
9841003 ret = wc_InitSha384 (& sha384_ctx );
1004+ if (ret == 0 ) {
1005+ did_init = 1 ;
1006+ }
9851007 }
9861008 if (ret == 0 ) {
9871009 ret = wc_Sha384Update (& sha384_ctx , data , (word32 )data_len );
9881010 }
9891011 if (ret == 0 ) {
9901012 ret = wc_Sha384Final (& sha384_ctx , sha384_digest );
9911013 }
992- wc_Sha384Free (& sha384_ctx );
1014+ if (did_init ) {
1015+ wc_Sha384Free (& sha384_ctx );
1016+ did_init = 0 ;
1017+ }
9931018 if (ret != 0 ) {
9941019 wolfBoot_printf ("FIT hash-1 (sha384): wc_Sha384 failed rc=%d\n" ,
9951020 ret );
@@ -1031,53 +1056,88 @@ void* fit_load_image_ex(void* fdt, const char* image, int* lenp,
10311056 data = (void * )fdt_getprop (fdt , off , "data" , & len );
10321057 load = fdt_getprop_address (fdt , off , "load" );
10331058 entry = fdt_getprop_address (fdt , off , "entry" );
1034- if (data != NULL && load != NULL && data != load ) {
1035- /* Detect compression unconditionally so we can warn (and fail
1036- * closed) when the build lacks support for it instead of
1037- * silently copying compressed bytes as if they were raw. */
1059+ if (data != NULL ) {
1060+ int is_gzip = 0 ;
1061+ int is_unknown_comp = 0 ;
1062+ /* Detect compression unconditionally (independent of whether
1063+ * a valid distinct load destination is available) so we can
1064+ * fail closed when the build lacks support, when the scheme
1065+ * is unknown, or when there is no place to decompress to -
1066+ * instead of silently passing compressed bytes through as
1067+ * raw. */
10381068 comp = (const char * )fdt_getprop (fdt , off , "compression" ,
10391069 & complen );
1040- if (comp != NULL && complen > 0 && strcmp (comp , "gzip" ) == 0 ) {
1041- #ifdef WOLFBOOT_GZIP
1042- uint32_t out_len = 0 ;
1043- int rc ;
1044- wolfBoot_printf ("Decompressing Image %s (gzip): "
1045- "%p -> %p (%d bytes)\n" , image , data , load , len );
1046- rc = wolfBoot_gunzip ((const uint8_t * )data , (uint32_t )len ,
1047- (uint8_t * )load , out_max , & out_len );
1048- if (rc != 0 ) {
1049- wolfBoot_printf ("FIT gunzip failed for %s: rc=%d "
1050- "(wrote %u bytes)\n" , image , rc , out_len );
1051- return NULL ;
1070+ if (comp != NULL && complen > 0 ) {
1071+ if (strcmp (comp , "gzip" ) == 0 ) {
1072+ is_gzip = 1 ;
1073+ }
1074+ else if (strcmp (comp , "none" ) != 0 ) {
1075+ is_unknown_comp = 1 ;
10521076 }
1053- len = (int )out_len ;
1054- wolfBoot_printf ("Decompressed %s: %u bytes\n" , image ,
1055- out_len );
1077+ }
1078+ if (load != NULL && data != load ) {
1079+ if (is_gzip ) {
1080+ #ifdef WOLFBOOT_GZIP
1081+ uint32_t out_len = 0 ;
1082+ int rc ;
1083+ wolfBoot_printf ("Decompressing Image %s (gzip): "
1084+ "%p -> %p (%d bytes)\n" , image , data , load , len );
1085+ rc = wolfBoot_gunzip ((const uint8_t * )data ,
1086+ (uint32_t )len , (uint8_t * )load , out_max , & out_len );
1087+ if (rc != 0 ) {
1088+ wolfBoot_printf ("FIT gunzip failed for %s: rc=%d "
1089+ "(wrote %u bytes)\n" , image , rc , out_len );
1090+ return NULL ;
1091+ }
1092+ len = (int )out_len ;
1093+ wolfBoot_printf ("Decompressed %s: %u bytes\n" , image ,
1094+ out_len );
10561095#else
1057- wolfBoot_printf ("FIT: subimage '%s' has compression="
1058- "\"gzip\" but WOLFBOOT_GZIP is not enabled in this "
1059- " build (rebuild with GZIP=1)\n" , image );
1060- return NULL ;
1096+ wolfBoot_printf ("FIT: subimage '%s' has compression="
1097+ "\"gzip\" but WOLFBOOT_GZIP is not enabled in "
1098+ "this build (rebuild with GZIP=1)\n" , image );
1099+ return NULL ;
10611100#endif
1062- }
1063- else {
1064- wolfBoot_printf ("Loading Image %s: %p -> %p (%d bytes)\n" ,
1065- image , data , load , len );
1066- memcpy (load , data , len );
1067- }
1101+ }
1102+ else if (is_unknown_comp ) {
1103+ /* Unknown compression scheme; fail closed rather
1104+ * than silently memcpy compressed bytes as raw. */
1105+ wolfBoot_printf ("FIT: subimage '%s' has unsupported "
1106+ "compression=\"%s\"\n" , image , comp );
1107+ return NULL ;
1108+ }
1109+ else {
1110+ wolfBoot_printf ("Loading Image %s: %p -> %p "
1111+ "(%d bytes)\n" , image , data , load , len );
1112+ memcpy (load , data , len );
1113+ }
10681114
10691115#ifdef WOLFBOOT_GZIP
1070- /* Defense-in-depth: verify FIT hash-1 against loaded bytes */
1071- if (fit_verify_hash (fdt , off , (const uint8_t * )load ,
1072- (uint32_t )len ) != 0 ) {
1073- wolfBoot_printf ("FIT hash verification failed for %s\n" ,
1074- image );
1075- return NULL ;
1076- }
1116+ /* Defense-in-depth: verify FIT hash-1 against loaded
1117+ * bytes */
1118+ if (fit_verify_hash (fdt , off , (const uint8_t * )load ,
1119+ (uint32_t )len ) != 0 ) {
1120+ wolfBoot_printf ("FIT hash verification failed for "
1121+ "%s\n" , image );
1122+ return NULL ;
1123+ }
10771124#endif
10781125
1079- /* load should always have entry, but if not use load address */
1080- data = (entry != NULL ) ? entry : load ;
1126+ /* load should always have entry, but if not use load
1127+ * address */
1128+ data = (entry != NULL ) ? entry : load ;
1129+ }
1130+ else if (is_gzip || is_unknown_comp ) {
1131+ /* Compression declared but no distinct destination to
1132+ * decompress into. Refuse rather than hand the caller
1133+ * a pointer to still-compressed bytes. */
1134+ wolfBoot_printf ("FIT: subimage '%s' declares "
1135+ "compression=\"%s\" but has no distinct load "
1136+ "destination (load=%p, data=%p); refusing to pass "
1137+ "compressed bytes through as raw\n" ,
1138+ image , comp , load , data );
1139+ return NULL ;
1140+ }
10811141 }
10821142 wolfBoot_printf ("Image %s: %p (%d bytes)\n" , image , data , len );
10831143 }
@@ -1093,7 +1153,7 @@ void* fit_load_image_ex(void* fdt, const char* image, int* lenp,
10931153
10941154void * fit_load_image (void * fdt , const char * image , int * lenp )
10951155{
1096- return fit_load_image_ex (fdt , image , lenp , 0xFFFFFFFFU );
1156+ return fit_load_image_ex (fdt , image , lenp , WOLFBOOT_FIT_MAX_DECOMP );
10971157}
10981158
10991159#endif /* (MMU || WOLFBOOT_FDT) && !BUILD_LOADER_STAGE1 */
0 commit comments