Delta updates, draft update mechanism with hdr replacement

pull/125/head
Daniele Lacamera 2021-06-03 10:22:04 +02:00
parent 7ff1887ad7
commit 13541ec046
6 changed files with 167 additions and 24 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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