mirror of https://github.com/wolfSSL/wolfBoot.git
Delta updates, draft update mechanism with hdr replacement
parent
7ff1887ad7
commit
13541ec046
|
@ -55,6 +55,7 @@
|
|||
#define HDR_SHA256 0x03
|
||||
#define HDR_IMG_TYPE 0x04
|
||||
#define HDR_IMG_DELTA_BASE 0x05
|
||||
#define HDR_PREDIFF_MANIFEST 0x40
|
||||
#define HDR_PUBKEY 0x10
|
||||
#define HDR_SIGNATURE 0x20
|
||||
#define HDR_SHA3_384 0x13
|
||||
|
@ -141,6 +142,10 @@ int wolfBoot_dualboot_candidate(void);
|
|||
#define ENCRYPT_KEY_SIZE 32 /* Chacha20 - 256bit */
|
||||
#define ENCRYPT_NONCE_SIZE 12 /* 96 bit*/
|
||||
|
||||
#ifdef DELTA_UPDATES
|
||||
int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr);
|
||||
#endif
|
||||
|
||||
int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce);
|
||||
int wolfBoot_get_encrypt_key(uint8_t *key, uint8_t *nonce);
|
||||
int wolfBoot_erase_encrypt_key(void);
|
||||
|
|
|
@ -217,6 +217,12 @@ ifneq ($(WOLFBOOT_VERSION),0)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DELTA_UPDATES),1)
|
||||
OBJS += src/delta.o
|
||||
CFLAGS+=-DDELTA_UPDATES
|
||||
CFLAGS+=-DDELTA_BLOCK_SIZE=$(DELTA_BLOCK_SIZE)
|
||||
endif
|
||||
|
||||
OBJS+=$(PUBLIC_KEY_OBJS)
|
||||
OBJS+=$(UPDATE_OBJS)
|
||||
|
||||
|
|
26
src/delta.c
26
src/delta.c
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "delta.h"
|
||||
|
||||
|
||||
#define ESC 0x7f
|
||||
|
@ -25,18 +26,6 @@ struct __attribute__((packed)) block_hdr {
|
|||
#define BLOCK_HDR_SIZE (sizeof (struct block_hdr))
|
||||
#define MAX_SRC_SIZE (1 << 24)
|
||||
|
||||
struct wb_patch_ctx {
|
||||
uint8_t *src_base;
|
||||
uint32_t src_size;
|
||||
uint8_t *patch_base;
|
||||
uint32_t patch_size;
|
||||
uint32_t p_off;
|
||||
int matching;
|
||||
uint16_t blk_off;
|
||||
};
|
||||
|
||||
typedef struct wb_patch_ctx WB_PATCH_CTX;
|
||||
|
||||
int wb_patch_init(WB_PATCH_CTX *bm, uint8_t *src, uint32_t ssz, uint8_t *patch, uint32_t psz)
|
||||
|
||||
{
|
||||
|
@ -115,13 +104,6 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
|
|||
return dst_off;
|
||||
}
|
||||
|
||||
struct wb_diff_ctx {
|
||||
uint8_t *src_a;
|
||||
uint8_t *src_b;
|
||||
uint32_t size_a, size_b, off_b;
|
||||
};
|
||||
|
||||
typedef struct wb_diff_ctx WB_DIFF_CTX;
|
||||
|
||||
int wb_diff_init(WB_DIFF_CTX *ctx, uint8_t *src_a, uint32_t len_a, uint8_t *src_b, uint32_t len_b)
|
||||
{
|
||||
|
@ -152,7 +134,7 @@ int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len)
|
|||
found = 0;
|
||||
if (p_off + BLOCK_HDR_SIZE > len)
|
||||
return p_off;
|
||||
while (((pa - ctx->src_a) < (ctx->size_a - BLOCK_HDR_SIZE)) && (p_off < len)) {
|
||||
while (((uint32_t)(pa - ctx->src_a) < (ctx->size_a - BLOCK_HDR_SIZE)) && (p_off < len)) {
|
||||
if ((ctx->size_b - ctx->off_b) < BLOCK_HDR_SIZE)
|
||||
break;
|
||||
if ((memcmp(pa, (ctx->src_b + ctx->off_b), BLOCK_HDR_SIZE) == 0)) {
|
||||
|
@ -164,7 +146,7 @@ int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len)
|
|||
match_len++;
|
||||
pa++;
|
||||
ctx->off_b++;
|
||||
if ((pa - ctx->src_a) >= ctx->size_a)
|
||||
if ((uint32_t)(pa - ctx->src_a) >= ctx->size_a)
|
||||
break;
|
||||
}
|
||||
hdr.esc = ESC;
|
||||
|
@ -299,7 +281,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
do {
|
||||
r = wb_diff(&dx, dest, blksz);
|
||||
if (r < 0)
|
||||
if (r < 0)
|
||||
exit(4);
|
||||
write(fd3, dest, r);
|
||||
len3 += r;
|
||||
|
|
|
@ -476,6 +476,84 @@ uint32_t wolfBoot_get_image_version(uint8_t part)
|
|||
return wolfBoot_get_blob_version(image);
|
||||
}
|
||||
|
||||
static uint32_t wolfBoot_get_blob_diffbase_version(uint8_t *blob)
|
||||
{
|
||||
uint32_t *delta_base = NULL;
|
||||
uint32_t *magic = NULL;
|
||||
magic = (uint32_t *)blob;
|
||||
if (*magic != WOLFBOOT_MAGIC)
|
||||
return 0;
|
||||
if (wolfBoot_find_header(blob + IMAGE_HEADER_OFFSET, HDR_IMG_DELTA_BASE, (void *)&delta_base) == 0)
|
||||
return 0;
|
||||
if (delta_base)
|
||||
return *delta_base;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t wolfBoot_get_diffbase_version(uint8_t part)
|
||||
{
|
||||
uint8_t *image = (uint8_t *)0x00000000;
|
||||
if(part == PART_UPDATE) {
|
||||
if (PARTN_IS_EXT(PART_UPDATE))
|
||||
{
|
||||
#ifdef EXT_FLASH
|
||||
ext_flash_check_read((uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS, hdr_cpy, IMAGE_HEADER_SIZE);
|
||||
hdr_cpy_done = 1;
|
||||
image = hdr_cpy;
|
||||
#endif
|
||||
} else {
|
||||
image = (uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
|
||||
}
|
||||
} else if (part == PART_BOOT) {
|
||||
if (PARTN_IS_EXT(PART_BOOT)) {
|
||||
#ifdef EXT_FLASH
|
||||
ext_flash_check_read((uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS, hdr_cpy, IMAGE_HEADER_SIZE);
|
||||
hdr_cpy_done = 1;
|
||||
image = hdr_cpy;
|
||||
#endif
|
||||
} else {
|
||||
image = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS;
|
||||
}
|
||||
}
|
||||
/* Don't check image against NULL to allow using address 0x00000000 */
|
||||
return wolfBoot_get_blob_diffbase_version(image);
|
||||
}
|
||||
|
||||
int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr)
|
||||
{
|
||||
uint8_t *image = NULL;
|
||||
uint32_t *magic = NULL;
|
||||
if(part == PART_UPDATE) {
|
||||
if (PARTN_IS_EXT(PART_UPDATE))
|
||||
{
|
||||
#ifdef EXT_FLASH
|
||||
ext_flash_check_read((uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS, hdr_cpy, IMAGE_HEADER_SIZE);
|
||||
hdr_cpy_done = 1;
|
||||
image = hdr_cpy;
|
||||
#endif
|
||||
} else {
|
||||
image = (uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
|
||||
}
|
||||
} else if (part == PART_BOOT) {
|
||||
if (PARTN_IS_EXT(PART_BOOT)) {
|
||||
#ifdef EXT_FLASH
|
||||
ext_flash_check_read((uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS, hdr_cpy, IMAGE_HEADER_SIZE);
|
||||
hdr_cpy_done = 1;
|
||||
image = hdr_cpy;
|
||||
#endif
|
||||
} else {
|
||||
image = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS;
|
||||
}
|
||||
}
|
||||
if (image) {
|
||||
magic = (uint32_t *)image;
|
||||
if (*magic != WOLFBOOT_MAGIC)
|
||||
return -1;
|
||||
return (int)wolfBoot_find_header(image + IMAGE_HEADER_OFFSET, HDR_PREDIFF_MANIFEST, ptr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t wolfBoot_get_image_type(uint8_t part)
|
||||
{
|
||||
uint16_t *type_field = NULL;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "hal.h"
|
||||
#include "spi_flash.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
#include "delta.h"
|
||||
|
||||
|
||||
#ifdef RAM_CODE
|
||||
|
@ -148,6 +149,67 @@ static int wolfBoot_copy_sector(struct wolfBoot_image *src, struct wolfBoot_imag
|
|||
return pos;
|
||||
}
|
||||
|
||||
#ifdef DELTA_UPDATES
|
||||
static uint8_t delta_blk[WOLFBOOT_SECTOR_SIZE];
|
||||
|
||||
static int wolfBoot_delta_update(struct wolfBoot_image *boot, struct wolfBoot_image *update, struct wolfBoot_image *swap)
|
||||
{
|
||||
int sector = 0;
|
||||
int ret;
|
||||
uint8_t flag;
|
||||
int hdr_size;
|
||||
uint8_t *manifest_hdr;
|
||||
/* Read encryption key/IV before starting the update */
|
||||
#ifdef EXT_ENCRYPTED
|
||||
wolfBoot_get_encrypt_key(key, nonce);
|
||||
#endif
|
||||
WB_PATCH_CTX ctx;
|
||||
|
||||
/* Check that image contains the header with the manifest before delta */
|
||||
hdr_size = wolfBoot_get_diffbase_hdr(PART_UPDATE, &manifest_hdr);
|
||||
if (hdr_size < 0)
|
||||
return -1;
|
||||
|
||||
ret = wb_patch_init(&ctx, boot->fw_base + IMAGE_HEADER_SIZE, boot->fw_size,
|
||||
update->fw_base + IMAGE_HEADER_SIZE, update->fw_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
while((sector * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE) {
|
||||
if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) {
|
||||
flag = SECT_FLAG_SWAPPING;
|
||||
wolfBoot_copy_sector(boot, swap, sector);
|
||||
if (((sector + 1) * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE)
|
||||
wolfBoot_set_update_sector_flag(sector, flag);
|
||||
}
|
||||
if (flag == SECT_FLAG_SWAPPING) {
|
||||
int len = 0;
|
||||
wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE);
|
||||
while (len < WOLFBOOT_SECTOR_SIZE) {
|
||||
ret = wb_patch(&ctx, delta_blk, WOLFBOOT_SECTOR_SIZE);
|
||||
if (ret > 0) {
|
||||
wb_flash_write(boot, sector * WOLFBOOT_SECTOR_SIZE, delta_blk + len, ret);
|
||||
len += ret;
|
||||
} else if (ret == 0) {
|
||||
flag = SECT_FLAG_UPDATED;
|
||||
wolfBoot_set_update_sector_flag(sector, flag);
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
flag = SECT_FLAG_UPDATED;
|
||||
wolfBoot_set_update_sector_flag(sector, flag);
|
||||
}
|
||||
sector++;
|
||||
}
|
||||
/* Put pre-diff manifest header for the new firmware */
|
||||
wb_flash_write(boot, 0, manifest_hdr, hdr_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
static int wolfBoot_update(int fallback_allowed)
|
||||
{
|
||||
uint32_t total_size = 0;
|
||||
|
@ -165,6 +227,7 @@ static int wolfBoot_update(int fallback_allowed)
|
|||
wolfBoot_open_image(&boot, PART_BOOT);
|
||||
wolfBoot_open_image(&swap, PART_SWAP);
|
||||
|
||||
|
||||
/* Use biggest size for the swap */
|
||||
total_size = boot.fw_size + IMAGE_HEADER_SIZE;
|
||||
if ((update.fw_size + IMAGE_HEADER_SIZE) > total_size)
|
||||
|
@ -183,7 +246,7 @@ static int wolfBoot_update(int fallback_allowed)
|
|||
*/
|
||||
|
||||
update_type = wolfBoot_get_image_type(PART_UPDATE);
|
||||
if (((update_type & 0x00FF) != HDR_IMG_TYPE_APP) || ((update_type & 0xFF00) != HDR_IMG_TYPE_AUTH))
|
||||
if (((update_type & 0x000F) != HDR_IMG_TYPE_APP) || ((update_type & 0xFF00) != HDR_IMG_TYPE_AUTH))
|
||||
return -1;
|
||||
if (!update.hdr_ok || (wolfBoot_verify_integrity(&update) < 0)
|
||||
|| (wolfBoot_verify_authenticity(&update) < 0)) {
|
||||
|
@ -193,9 +256,15 @@ static int wolfBoot_update(int fallback_allowed)
|
|||
if ( !fallback_allowed &&
|
||||
(wolfBoot_update_firmware_version() <= wolfBoot_current_firmware_version()) )
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef DELTA_UPDATES
|
||||
if ((update_type & 0x00F0) == HDR_IMG_TYPE_DIFF) {
|
||||
return wolfBoot_delta_update(&boot, &update, &swap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
hal_flash_unlock();
|
||||
#ifdef EXT_FLASH
|
||||
ext_flash_unlock();
|
||||
|
|
|
@ -48,6 +48,8 @@ ifeq ($(ARCH),)
|
|||
WOLFBOOT_LOAD_ADDRESS?=0x200000
|
||||
WOLFBOOT_LOAD_DTS_ADDRESS?=0x400000
|
||||
WOLFBOOT_SMALL_STACK?=0
|
||||
DELTA_UPDATES?=0
|
||||
DELTA_BLOCK_SIZE?=256
|
||||
endif
|
||||
|
||||
CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO_DRIVERS \
|
||||
|
@ -59,4 +61,5 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO_DRIVERS
|
|||
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
|
||||
WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \
|
||||
WOLFBOOT_LOAD_DTS_ADDRESS WOLFBOOT_DTS_BOOT_ADDRESS WOLFBOOT_DTS_UPDATE_ADDRESS \
|
||||
WOLFBOOT_SMALL_STACK
|
||||
WOLFBOOT_SMALL_STACK DELTA_UPDATES DELTA_BLOCK_SIZE
|
||||
|
||||
|
|
Loading…
Reference in New Issue