Skip to content

Commit fb6ca43

Browse files
bigbrettdanielinux
authored andcommitted
WIP: structure is there, but some major issues. See WOLFBOOT-ELF-LOADER-GAPS.md and video
1 parent 7caf579 commit fb6ca43

6 files changed

Lines changed: 337 additions & 1090 deletions

File tree

include/elf.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,29 @@ typedef struct elf64_program_header {
136136
} elf64_program_header;
137137

138138

139+
/* support byte swapping if testing/reading an elf with different endianess */
140+
#if defined(ELF_PARSER) || defined(ELF_ENDIAN_SUPPORT)
141+
#ifdef BIG_ENDIAN_ORDER
142+
#define GET16(x) (( is_le) ? __builtin_bswap16(x) : (x))
143+
#define GET32(x) (( is_le) ? __builtin_bswap32(x) : (x))
144+
#define GET64(x) (( is_le) ? __builtin_bswap64(x) : (x))
145+
#else
146+
#define GET16(x) ((!is_le) ? __builtin_bswap16(x) : (x))
147+
#define GET32(x) ((!is_le) ? __builtin_bswap32(x) : (x))
148+
#define GET64(x) ((!is_le) ? __builtin_bswap64(x) : (x))
149+
#endif
150+
#else
151+
#define GET16(x) (x)
152+
#define GET32(x) (x)
153+
#define GET64(x) (x)
154+
#endif
155+
156+
#define GET_H64(name) (is_elf32 ? GET32(h32->name) : GET64(h64->name))
157+
#define GET_H32(name) (is_elf32 ? GET32(h32->name) : GET32(h64->name))
158+
#define GET_H16(name) (is_elf32 ? GET16(h32->name) : GET16(h64->name))
159+
#define GET_E64(name) (is_elf32 ? GET32(e32->name) : GET64(e64->name))
160+
#define GET_E32(name) (is_elf32 ? GET32(e32->name) : GET32(e64->name))
161+
139162
typedef int (*elf_mmu_map_cb)(uint64_t, uint64_t, uint32_t);
140163
int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb);
141164
int elf_load_image(uint8_t *image, uintptr_t *entry);

include/wolfboot/wolfboot.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ extern "C" {
7979
#define HDR_SIGNATURE 0x20
8080
#define HDR_POLICY_SIGNATURE 0x21
8181
#define HDR_SECONDARY_SIGNATURE 0x22
82+
#define HDR_ELF_SCATTERED_HASH 0x23
8283
#define HDR_PADDING 0xFF
8384

8485
/* Auth Key types */
@@ -291,6 +292,9 @@ extern "C" {
291292
/* now just an intermediary state, update state will always be either new or
292293
* updating before the application boots*/
293294
#define IMG_STATE_FINAL_FLAGS 0x30
295+
/* ELF loading state - only valid on boot partition so doesn't conflict with
296+
* IMAGE_STATE_UPDATING */
297+
#define IMG_STATE_ELF_LOADING 0x70
294298
#define IMG_STATE_TESTING 0x10
295299
#define IMG_STATE_SUCCESS 0x00
296300
#define FLASH_BYTE_ERASED 0xFF
@@ -300,6 +304,7 @@ extern "C" {
300304
#define IMG_STATE_UPDATING 0x8F
301305
#define IMG_STATE_TESTING 0xEF
302306
#define IMG_STATE_FINAL_FLAGS 0xBF
307+
#define IMG_STATE_ELF_LOADING 0x70
303308
#define IMG_STATE_SUCCESS 0xFF
304309
#define FLASH_BYTE_ERASED 0x00
305310
#define FLASH_WORD_ERASED 0x00000000UL

src/elf.c

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,28 +42,6 @@
4242
#endif
4343
#endif
4444

45-
/* support byte swapping if testing/reading an elf with different endianess */
46-
#if defined(ELF_PARSER) || defined(ELF_ENDIAN_SUPPORT)
47-
#ifdef BIG_ENDIAN_ORDER
48-
#define GET16(x) (( is_le) ? __builtin_bswap16(x) : (x))
49-
#define GET32(x) (( is_le) ? __builtin_bswap32(x) : (x))
50-
#define GET64(x) (( is_le) ? __builtin_bswap64(x) : (x))
51-
#else
52-
#define GET16(x) ((!is_le) ? __builtin_bswap16(x) : (x))
53-
#define GET32(x) ((!is_le) ? __builtin_bswap32(x) : (x))
54-
#define GET64(x) ((!is_le) ? __builtin_bswap64(x) : (x))
55-
#endif
56-
#else
57-
#define GET16(x) (x)
58-
#define GET32(x) (x)
59-
#define GET64(x) (x)
60-
#endif
61-
62-
#define GET_H64(name) (is_elf32 ? GET32(h32->name) : GET64(h64->name))
63-
#define GET_H32(name) (is_elf32 ? GET32(h32->name) : GET32(h64->name))
64-
#define GET_H16(name) (is_elf32 ? GET16(h32->name) : GET16(h64->name))
65-
#define GET_E64(name) (is_elf32 ? GET32(e32->name) : GET64(e64->name))
66-
#define GET_E32(name) (is_elf32 ? GET32(e32->name) : GET32(e64->name))
6745

6846
/* Loader for elf32 or elf64 format program headers
6947
* Returns the entry point function

src/image.c

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
#ifdef WOLFBOOT_HASH_SHA3_384
5252
#include <wolfssl/wolfcrypt/sha3.h>
5353
#endif
54+
#ifdef WOLFBOOT_ELF
55+
#include "elf.h"
56+
#endif
5457

5558
/* Globals */
5659
static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE];
@@ -770,6 +773,39 @@ static uint8_t *get_sha_block(struct wolfBoot_image *img, uint32_t offset)
770773
#endif
771774
return (uint8_t *)(img->fw_base + offset);
772775
}
776+
/**
777+
* @brief Get a block of data to be hashed from a specific memory address.
778+
*
779+
* This function retrieves a block of data to be hashed from a specific memory address.
780+
* It behaves similarly to get_sha_block but takes a direct pointer instead of an offset.
781+
*
782+
* @param img The image to retrieve the data from.
783+
* @param addr The memory address to read the data from.
784+
* @return A pointer to the data block.
785+
*/
786+
static uint8_t *get_sha_block_ptr(struct wolfBoot_image *img, const uint8_t *addr)
787+
{
788+
uint32_t offset;
789+
790+
/* Calculate offset from base address */
791+
if ((uintptr_t)addr < (uintptr_t)img->fw_base) {
792+
return NULL;
793+
}
794+
795+
offset = (uint32_t)((uintptr_t)addr - (uintptr_t)img->fw_base);
796+
797+
if (offset > img->fw_size) {
798+
return NULL;
799+
}
800+
801+
#ifdef EXT_FLASH
802+
if (PART_IS_EXT(img)) {
803+
ext_flash_check_read((uintptr_t)addr, ext_hash_block, WOLFBOOT_SHA_BLOCK_SIZE);
804+
return ext_hash_block;
805+
} else
806+
#endif
807+
return (uint8_t *)addr;
808+
}
773809

774810
#ifdef EXT_FLASH
775811
static uint8_t hdr_cpy[IMAGE_HEADER_SIZE];
@@ -1061,6 +1097,147 @@ static void key_sha3_384(uint8_t key_slot, uint8_t *hash)
10611097
#endif /* WOLFBOOT_NO_SIGN */
10621098
#endif /* SHA3-384 */
10631099

1100+
1101+
#ifdef WOLFBOOT_ELF
1102+
/**
1103+
* @brief Compute the scattered hash by hashing PT_LOAD segments at their XIP
1104+
* addresses. Note: This function assumes that the destination addresses for elf
1105+
* loading have the same access patterns as the memory represented by img.
1106+
* (e.g. if BOOT partition is external, then reads/writes to the load address
1107+
* will use ext_flash_read/ext_flash_write.
1108+
*
1109+
* @param img Pointer to the wolfBoot image
1110+
* @param hash Buffer to store the computed hash (must be at least
1111+
* WOLFBOOT_SHA_DIGEST_SIZE bytes)
1112+
* @return 0 on success, negative value on error
1113+
*/
1114+
static int wolfBoot_compute_scattered_hash(struct wolfBoot_image *img, uint8_t *hash)
1115+
{
1116+
uint8_t elf_header_buf[sizeof(elf64_header)];
1117+
uint8_t program_header_buf[sizeof(elf64_program_header)];
1118+
elf32_header* h32;
1119+
elf64_header* h64;
1120+
uint16_t entry_count, entry_size;
1121+
uint32_t ph_offset;
1122+
int is_elf32, is_le, i;
1123+
#if defined(WOLFBOOT_HASH_SHA256)
1124+
wc_Sha256 sha256_ctx;
1125+
#elif defined(WOLFBOOT_HASH_SHA384)
1126+
wc_Sha384 sha384_ctx;
1127+
#elif defined(WOLFBOOT_HASH_SHA3_384)
1128+
wc_Sha3 sha3_384_ctx;
1129+
#endif
1130+
1131+
#ifdef EXT_FLASH
1132+
if (PART_IS_EXT(img)) {
1133+
/* Read ELF header from external flash */
1134+
ext_flash_check_read((uintptr_t)(img->fw_base), elf_header_buf, sizeof(elf64_header));
1135+
} else
1136+
#endif
1137+
{
1138+
memcpy(elf_header_buf, (void*)(img->fw_base), sizeof(elf64_header));
1139+
}
1140+
1141+
h32 = (elf32_header*)elf_header_buf;
1142+
h64 = (elf64_header*)elf_header_buf;
1143+
1144+
/* Verify ELF header */
1145+
if (memcmp(h32->ident, ELF_IDENT_STR, 4) != 0) {
1146+
return -1; /* not valid header identifier */
1147+
}
1148+
1149+
/* Load class and endianess */
1150+
is_elf32 = (h32->ident[4] == ELF_CLASS_32);
1151+
is_le = (h32->ident[5] == ELF_ENDIAN_LITTLE);
1152+
(void)is_le;
1153+
1154+
/* Initialize hash context */
1155+
#if defined(WOLFBOOT_HASH_SHA256)
1156+
wc_InitSha256(&sha256_ctx);
1157+
#elif defined(WOLFBOOT_HASH_SHA384)
1158+
wc_InitSha384(&sha384_ctx);
1159+
#elif defined(WOLFBOOT_HASH_SHA3_384)
1160+
wc_Sha3_384_Init(&sha3_384_ctx, NULL, INVALID_DEVID);
1161+
#endif
1162+
1163+
/* Get program headers info */
1164+
ph_offset = is_elf32 ? GET32(h32->ph_offset) : GET32(h64->ph_offset);
1165+
entry_size = is_elf32 ? GET16(h32->ph_entry_size) : GET16(h64->ph_entry_size);
1166+
entry_count = is_elf32 ? GET16(h32->ph_entry_count) : GET16(h64->ph_entry_count);
1167+
1168+
/* Hash each loadable segment directly from its physical address */
1169+
for (i = 0; i < entry_count; i++) {
1170+
elf32_program_header* phdr32;
1171+
elf64_program_header* phdr64;
1172+
uint32_t type;
1173+
uintptr_t paddr;
1174+
uintptr_t file_size;
1175+
1176+
/* Read program header into buffer */
1177+
#ifdef EXT_FLASH
1178+
if (PART_IS_EXT(img)) {
1179+
ext_flash_check_read((uintptr_t)(img->fw_base) + ph_offset + (i * entry_size),
1180+
program_header_buf, entry_size);
1181+
} else
1182+
#endif
1183+
{
1184+
memcpy(program_header_buf,
1185+
(uint8_t*)(img->fw_base) + ph_offset + (i * entry_size),
1186+
entry_size);
1187+
}
1188+
1189+
1190+
phdr32 = (elf32_program_header*)program_header_buf;
1191+
phdr64 = (elf64_program_header*)program_header_buf;
1192+
type = (is_elf32 ? GET32(phdr32->type) : GET32(phdr64->type));
1193+
paddr = (is_elf32 ? GET32(phdr32->paddr) : GET64(phdr64->paddr));
1194+
file_size = (is_elf32 ? GET32(phdr32->file_size) : GET64(phdr64->file_size));
1195+
1196+
/* Only hash PT_LOAD segments with non-zero size */
1197+
if (type == ELF_PT_LOAD && file_size > 0) {
1198+
#ifdef DEBUG_ELF
1199+
wolfBoot_printf("Hashing segment at %p (%d bytes)\r\n", (void*)paddr, (uint32_t)file_size);
1200+
#endif
1201+
/* Hash the segment data from physical address in blocks */
1202+
uint32_t pos = 0;
1203+
while (pos < file_size) {
1204+
uint8_t *block;
1205+
uint32_t blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1206+
1207+
if (pos + blksz > file_size) {
1208+
blksz = file_size - pos;
1209+
}
1210+
1211+
block = get_sha_block_ptr(img, (const uint8_t *)(paddr + pos));
1212+
if (block == NULL) {
1213+
return -1;
1214+
}
1215+
1216+
#if defined(WOLFBOOT_HASH_SHA256)
1217+
wc_Sha256Update(&sha256_ctx, block, blksz);
1218+
#elif defined(WOLFBOOT_HASH_SHA384)
1219+
wc_Sha384Update(&sha384_ctx, block, blksz);
1220+
#elif defined(WOLFBOOT_HASH_SHA3_384)
1221+
wc_Sha3_384_Update(&sha3_384_ctx, block, blksz);
1222+
#endif
1223+
pos += blksz;
1224+
}
1225+
}
1226+
}
1227+
1228+
/* Finalize hash */
1229+
#if defined(WOLFBOOT_HASH_SHA256)
1230+
wc_Sha256Final(&sha256_ctx, hash);
1231+
#elif defined(WOLFBOOT_HASH_SHA384)
1232+
wc_Sha384Final(&sha384_ctx, hash);
1233+
#elif defined(WOLFBOOT_HASH_SHA3_384)
1234+
wc_Sha3_384_Final(&sha3_384_ctx, hash);
1235+
#endif
1236+
1237+
return 0;
1238+
}
1239+
#endif /* WOLFBOOT_ELF */
1240+
10641241
/**
10651242
* @brief Convert a 32-bit integer from little-endian to native byte order.
10661243
*

0 commit comments

Comments
 (0)