diff --git a/Makefile b/Makefile index 31165c9a..45d4c104 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,6 @@ tools/ed25519/ed25519_sign: ed25519.der: tools/ed25519/ed25519_sign tools/ed25519/ed25519_keygen src/ed25519_pub_key.c - factory.bin: $(BOOT_IMG) wolfboot-align.bin tools/ed25519/ed25519_sign ed25519.der tools/ed25519/ed25519_sign $(BOOT_IMG) ed25519.der 1 cat wolfboot-align.bin $(BOOT_IMG).v1.signed > $@ diff --git a/include/image.h b/include/image.h new file mode 100644 index 00000000..2668bc05 --- /dev/null +++ b/include/image.h @@ -0,0 +1,59 @@ +#ifndef IMAGE_H +#define IMAGE_H +#include +#include + +#define IMAGE_HEADER_SIZE 256 +#define IMAGE_HEADER_OFFSET (2 * sizeof(uint32_t)) + +#define WOLFBOOT_MAGIC 0x464C4F57 /* WOLF */ +#define WOLFBOOT_MAGIC_TRAIL 0x544F4F42 /* BOOT */ + +#define HDR_END 0x00 +#define HDR_VERSION 0x01 +#define HDR_TIMESTAMP 0x02 +#define HDR_SHA256 0x03 +#define HDR_PUBKEY 0x10 +#define HDR_SIGNATURE 0x20 +#define HDR_PADDING 0xFF + +#define PART_BOOT 0 +#define PART_UPDATE 1 +#define PART_SWAP 2 + +#define IMG_STATE_NEW 0xFF +#define IMG_STATE_UPDATING 0x70 +#define IMG_STATE_TESTING 0x10 +#define IMG_STATE_SUCCESS 0x00 + +#define SECT_FLAG_NEW 0x0F +#define SECT_FLAG_SWAPPING 0x07 +#define SECT_FLAG_BACKUP 0x03 +#define SECT_FLAG_UPDATED 0x00 + + +struct wolfBoot_image { + uint8_t *hdr; + uint8_t *trailer; + int hdr_ok; + int signature_ok; + int sha_ok; + uint8_t *fw_base; + uint32_t fw_size; + uint8_t part; +}; + + +int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part); +int wolfBoot_verify_integrity(struct wolfBoot_image *img); +int wolfBoot_verify_authenticity(struct wolfBoot_image *img); +int wolfBoot_set_partition_state(uint8_t part, uint8_t newst); +int wolfBoot_set_sector_flag(uint8_t part, uint8_t sector, uint8_t newflag); +int wolfBoot_get_partition_state(uint8_t part, uint8_t *st); +int wolfBoot_get_sector_flag(uint8_t part, uint8_t sector, uint8_t *flag); +int wolfBoot_copy(uint32_t src, uint32_t dst, uint32_t size); +void wolfBoot_erase_partition(uint8_t part); +void wolfBoot_update_trigger(void); +void wolfBoot_success(void); + +#endif /* IMAGE_H */ diff --git a/include/loader.h b/include/loader.h new file mode 100644 index 00000000..d7af315b --- /dev/null +++ b/include/loader.h @@ -0,0 +1,21 @@ +#ifndef LOADER_H +#define LOADER_H + +#if defined(WOLFBOOT_SIGN_EC256) + extern const unsigned char ecdsa_pub_key[]; + extern unsigned int ecdsa_pub_key_len; +# define KEY_BUFFER ecdsa_pub_key +# define KEY_LEN ecdsa_pub_key_len +# define IMAGE_SIGNATURE_SIZE (72) +#elif defined(WOLFBOOT_SIGN_ED25519) + extern const unsigned char ed25519_pub_key[]; + extern unsigned int ed25519_pub_key_len; +# define KEY_BUFFER ed25519_pub_key +# define KEY_LEN ed25519_pub_key_len +# define IMAGE_SIGNATURE_SIZE (64) +#else +# error "No public key available for given signing algorithm." +#endif /* Algorithm selection */ + + +#endif /* LOADER_H */ diff --git a/src/image.c b/src/image.c new file mode 100644 index 00000000..a50c553d --- /dev/null +++ b/src/image.c @@ -0,0 +1,323 @@ +/* image.c + * + * Copyright (C) 2018 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include +#include +#include +#include +#include + +#ifdef WOLFBOOT_SIGN_ED25519 +#include +static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig) +{ + int ret, res; + ed25519_key ed; + ret = wc_ed25519_init(&ed); + if (ret < 0) { + /* Failed to initialize key */ + return -1; + } + ret = wc_ed25519_import_public(KEY_BUFFER, KEY_LEN, &ed); + if (ret < 0) { + /* Failed to import ed25519 key */ + return -1; + } + ret = wc_ed25519_verify_msg(sig, IMAGE_SIGNATURE_SIZE, hash, SHA256_DIGEST_SIZE, &res, &ed); + if ((ret < 0) || (res == 0)) { + return -1; + } + return 0; +} +#endif + + +static uint8_t get_header(struct wolfBoot_image *img, uint8_t type, uint8_t **ptr) +{ + uint8_t *p = img->hdr + IMAGE_HEADER_OFFSET; + while (*p != 0) { + if (*p == HDR_PADDING) { + p++; + continue; + } + if (*p == type) { + p++; + *ptr = (p + 1); + return *p; + } + p++; + p += (*p + 1); + } + *ptr = NULL; + return 0; +} + +int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part) +{ + uint32_t *magic; + uint32_t *size; + if (!img) + return -1; + memset(img, 0, sizeof(struct wolfBoot_image)); + + if (part == PART_BOOT) + img->hdr = (void *)WOLFBOOT_PARTITION_BOOT_ADDRESS; + else if (part == PART_UPDATE) + img->hdr = (void *)WOLFBOOT_PARTITION_UPDATE_ADDRESS; + else + return -1; + magic = (uint32_t *)(img->hdr); + if (*magic != WOLFBOOT_MAGIC) + return -1; + size = (uint32_t *)(img->hdr + sizeof (uint32_t)); + + if (*size >= WOLFBOOT_PARTITION_SIZE) + return -1; + img->part = part; + img->hdr_ok = 1; + img->fw_size = *size; + img->fw_base = img->hdr + IMAGE_HEADER_SIZE; + img->trailer = img->hdr + WOLFBOOT_PARTITION_SIZE; + return 0; +} + +static int image_hash(struct wolfBoot_image *img, uint8_t *hash) +{ + uint8_t *stored_sha, *end_sha; + uint8_t stored_sha_len; + uint8_t *p = img->hdr; + uint8_t *fw_end = img->fw_base + img->fw_size; + int blksz; + wc_Sha256 sha256_ctx; + if (!img || !img->hdr) + return -1; + + stored_sha_len = get_header(img, HDR_SHA256, &stored_sha); + if (stored_sha_len != SHA256_DIGEST_SIZE) + return -1; + wc_InitSha256(&sha256_ctx); + end_sha = stored_sha - 2; + while (p < end_sha) { + blksz = SHA256_BLOCK_SIZE; + if (end_sha - p < blksz) + blksz = end_sha - p; + wc_Sha256Update(&sha256_ctx, p, blksz); + p += blksz; + } + p = img->fw_base; + while(p < fw_end) { + blksz = SHA256_BLOCK_SIZE; + if (fw_end - p < blksz) + blksz = fw_end - p; + wc_Sha256Update(&sha256_ctx, p, blksz); + p += blksz; + } + wc_Sha256Final(&sha256_ctx, hash); + return 0; +} + +static void key_hash(uint8_t *hash) +{ + int blksz; + unsigned int i = 0; + wc_Sha256 sha256_ctx; + wc_InitSha256(&sha256_ctx); + while(i < KEY_LEN) + { + blksz = SHA256_BLOCK_SIZE; + if ((i + blksz) > KEY_LEN) + blksz = KEY_LEN - i; + wc_Sha256Update(&sha256_ctx, (KEY_BUFFER + i), blksz); + i += blksz; + } + wc_Sha256Final(&sha256_ctx, hash); +} + +static uint8_t digest[SHA256_DIGEST_SIZE]; +int wolfBoot_verify_integrity(struct wolfBoot_image *img) +{ + uint8_t *stored_sha; + uint8_t stored_sha_len; + stored_sha_len = get_header(img, HDR_SHA256, &stored_sha); + if (stored_sha_len != SHA256_DIGEST_SIZE) + return -1; + if (image_hash(img, digest) != 0) + return -1; + if (memcmp(digest, stored_sha, stored_sha_len) != 0) + return -1; + img->sha_ok = 1; + return 0; +} + +static uint8_t verification[IMAGE_SIGNATURE_SIZE]; +int wolfBoot_verify_authenticity(struct wolfBoot_image *img) +{ + uint8_t *stored_signature; + uint8_t stored_signature_size; + uint8_t *pubkey_hint; + uint8_t pubkey_hint_size; + + stored_signature_size = get_header(img, HDR_SIGNATURE, &stored_signature); + if (stored_signature_size != IMAGE_SIGNATURE_SIZE) + return -1; + pubkey_hint_size = get_header(img, HDR_PUBKEY, &pubkey_hint); + if (pubkey_hint_size == SHA256_DIGEST_SIZE) { + key_hash(digest); + if (memcmp(digest, pubkey_hint, SHA256_DIGEST_SIZE) != 0) + return -1; + } + + if (image_hash(img, digest) != 0) + return -1; + if (wolfBoot_verify_signature(digest, stored_signature) != 0) + return -1; + img->signature_ok = 1; + return 0; +} + +static uint8_t *get_trailer(uint8_t part) +{ + if (part == PART_BOOT) + return (void *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE); + else if (part == PART_UPDATE) + return (void *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE); + else + return NULL; +} + +int wolfBoot_set_partition_state(uint8_t part, uint8_t newst) +{ + uint8_t *trailer_end = get_trailer(part); + uint32_t *magic; + uint8_t *state; + uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL; + if (!trailer_end) + return -1; + magic = (uint32_t *)(trailer_end - sizeof(uint32_t)); + if (*magic != WOLFBOOT_MAGIC_TRAIL) + hal_flash_write((uint32_t)magic, (void *)&wolfboot_magic_trail, sizeof(uint32_t)); + state = (trailer_end - sizeof(uint32_t)) - 1; + if (*state != newst) + hal_flash_write((uint32_t)state, (void *)&newst, 1); + return 0; +} + +int wolfBoot_set_sector_flag(uint8_t part, uint8_t sector, uint8_t newflag) +{ + uint8_t *trailer_end = get_trailer(part); + uint32_t *magic; + uint8_t *flags; + uint8_t fl_value; + uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL; + uint8_t pos = sector >> 1; + if (!trailer_end) + return -1; + magic = (uint32_t *)(trailer_end - sizeof(uint32_t)); + if (*magic != WOLFBOOT_MAGIC_TRAIL) + hal_flash_write((uint32_t)magic, (void *)&wolfboot_magic_trail, sizeof(uint32_t)); + flags = (trailer_end - sizeof(uint32_t)) - pos; + if (sector == (pos << 1)) + fl_value = (*flags & 0xF0) | (newflag & 0x0F); + else + fl_value = ((newflag & 0x0F) << 4) | (*flags & 0x0F); + if (fl_value != *flags) + hal_flash_write((uint32_t)flags, &fl_value, 1); + return 0; +} + +int wolfBoot_get_partition_state(uint8_t part, uint8_t *st) +{ + uint8_t *trailer_end = get_trailer(part); + uint32_t *magic; + uint8_t *state; + if (trailer_end) + return -1; + magic = (uint32_t *)(trailer_end - sizeof(uint32_t)); + if (*magic != WOLFBOOT_MAGIC_TRAIL) + return -1; + state = (trailer_end - sizeof(uint32_t)) - 1; + *st = *state; + return 0; +} + +int wolfBoot_get_sector_flag(uint8_t part, uint8_t sector, uint8_t *flag) +{ + uint8_t *trailer_end = get_trailer(part); + uint32_t *magic; + uint8_t *flags; + uint8_t fl_value; + uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL; + uint8_t pos = sector >> 1; + if (!trailer_end) + return -1; + magic = (uint32_t *)(trailer_end - sizeof(uint32_t)); + if (*magic != WOLFBOOT_MAGIC_TRAIL) + return -1; + flags = (trailer_end - sizeof(uint32_t)) - pos; + if (sector == (pos << 1)) + *flag = *flags & 0x0F; + else + *flag = (*flags & 0xF0) >> 4; + return 0; +} + +int wolfBoot_copy(uint32_t src, uint32_t dst, uint32_t size) +{ + uint32_t *content; + uint32_t pos = 0; + if (src == dst) + return 0; + if ((src & 0x03) || (dst & 0x03)) + return -1; + while (pos < size) { + content = (uint32_t *)(src + pos); + hal_flash_write(dst + pos, (void *)content, sizeof(uint32_t)); + pos += sizeof(uint32_t); + } + return pos; +} + +void wolfBoot_erase_partition(uint8_t part) +{ + if (part == PART_BOOT) + hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS, WOLFBOOT_PARTITION_SIZE); + if (part == PART_UPDATE) + hal_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS, WOLFBOOT_PARTITION_SIZE); +#ifdef WOLFBOOT_PARTITION_SWAP_ADDRESS + if (part == PART_SWAP) + hal_flash_erase(WOLFBOOT_PARTITION_SWAP_ADDRESS, WOLFBOOT_SECTOR_SIZE); +#endif +} + +void wolfBoot_update_trigger(void) +{ + uint8_t st = IMG_STATE_UPDATING; + hal_flash_unlock(); + wolfBoot_set_partition_state(PART_UPDATE, st); + hal_flash_lock(); +} + +void wolfBoot_success(void) +{ + uint8_t st = IMG_STATE_SUCCESS; + hal_flash_unlock(); + wolfBoot_set_partition_state(PART_BOOT, st); + hal_flash_lock(); +} diff --git a/src/loader.c b/src/loader.c new file mode 100644 index 00000000..e3dc56b7 --- /dev/null +++ b/src/loader.c @@ -0,0 +1,122 @@ +/* loader.c + * + * Copyright (C) 2018 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include +#include +#include + + +extern void do_boot(const uint32_t *app_offset); + +static int wolfBoot_update(void) +{ + uint32_t total_size; + uint32_t sector_size = WOLFBOOT_SECTOR_SIZE; + uint32_t sector = 0; + uint8_t flag, st; + struct wolfBoot_image update; + + if ((wolfBoot_open_image(&update, PART_BOOT) < 0) || + (wolfBoot_verify_integrity(&update) < 0) || + (wolfBoot_verify_authenticity(&update) < 0)) { + return -1; + } + + total_size = update.fw_size + IMAGE_HEADER_SIZE; + hal_flash_unlock(); + + while ((sector * sector_size) < total_size) { + if ((wolfBoot_get_sector_flag(PART_UPDATE, sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) { + flag = SECT_FLAG_SWAPPING; + hal_flash_erase(WOLFBOOT_PARTITION_SWAP_ADDRESS, WOLFBOOT_SECTOR_SIZE); + wolfBoot_copy(WOLFBOOT_PARTITION_UPDATE_ADDRESS + sector * sector_size, + WOLFBOOT_PARTITION_SWAP_ADDRESS, + WOLFBOOT_SECTOR_SIZE); + wolfBoot_set_sector_flag(PART_UPDATE, sector, flag); + } + if (flag == SECT_FLAG_SWAPPING) { + uint32_t size = total_size - (sector * sector_size); + if (size > sector_size) + size = sector_size; + flag = SECT_FLAG_BACKUP; + hal_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS + sector * sector_size, + WOLFBOOT_SECTOR_SIZE); + wolfBoot_copy(WOLFBOOT_PARTITION_BOOT_ADDRESS + sector * sector_size, + WOLFBOOT_PARTITION_UPDATE_ADDRESS + sector * sector_size, + WOLFBOOT_SECTOR_SIZE); + wolfBoot_set_sector_flag(PART_UPDATE, sector, flag); + } + if (flag == SECT_FLAG_BACKUP) { + uint32_t size = total_size - (sector * sector_size); + if (size > sector_size) + size = sector_size; + flag = SECT_FLAG_UPDATED; + hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS + sector * sector_size, + sector_size); + wolfBoot_copy(WOLFBOOT_PARTITION_SWAP_ADDRESS, + WOLFBOOT_PARTITION_BOOT_ADDRESS + sector * sector_size, + size); + wolfBoot_set_sector_flag(PART_UPDATE, sector, flag); + } + sector++; + } + while((sector * sector_size) < WOLFBOOT_PARTITION_SIZE) { + hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS + sector * sector_size, + sector_size); + hal_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS + sector * sector_size, + sector_size); + sector++; + } + hal_flash_erase(WOLFBOOT_PARTITION_SWAP_ADDRESS, WOLFBOOT_SECTOR_SIZE); + st = IMG_STATE_TESTING; + wolfBoot_set_partition_state(PART_BOOT, st); + hal_flash_lock(); + return 0; +} + +static void wolfBoot_start(void) +{ + uint8_t st; + struct wolfBoot_image boot; + if ((wolfBoot_open_image(&boot, PART_BOOT) < 0) || + (wolfBoot_verify_integrity(&boot) < 0) || + (wolfBoot_verify_authenticity(&boot) < 0)) { + if (wolfBoot_update() < 0) { + while(1) + /* panic */; + } + } + if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && (st == IMG_STATE_UPDATING)) { + wolfBoot_update(); + } else if ((wolfBoot_get_partition_state(PART_BOOT, &st) == 0) && (st == IMG_STATE_TESTING)) { + wolfBoot_update_trigger(); + wolfBoot_update(); + } + do_boot((void *)boot.fw_base); +} + +int main(void) +{ + hal_init(); + wolfBoot_start(); + while(1) + ; + return 0; +} diff --git a/src/wolfboot.c b/src/wolfboot.c index 8744d046..74d25da1 100644 --- a/src/wolfboot.c +++ b/src/wolfboot.c @@ -1,4 +1,4 @@ -/* startup_bl.c +/* wolfboot.c * * Copyright (C) 2018 wolfSSL Inc. * @@ -28,7 +28,8 @@ extern unsigned int _end_bss; extern uint32_t *END_STACK; -void main(void); +extern void main(void); + void isr_reset(void) { unsigned int *src, *dst; diff --git a/tools/ed25519/ed25519_sign.c b/tools/ed25519/ed25519_sign.c index 11f8035d..8676a7d1 100644 --- a/tools/ed25519/ed25519_sign.c +++ b/tools/ed25519/ed25519_sign.c @@ -25,12 +25,13 @@ #include #include #include -#include #include + +#define WOLFBOOT_SIGN_ED25519 + #include "target.h" - -#define IMAGE_FIRMWARE_OFFSET 256 - +#include "image.h" +#include "loader.h" void print_buf(uint8_t *buf, int len) { @@ -70,17 +71,13 @@ int main(int argc, char *argv[]) uint8_t signature[ED25519_SIG_SIZE]; uint8_t *final; int total_size; - struct image_header *hdr; - uint8_t header_buffer[IMAGE_FIRMWARE_OFFSET]; - struct image_tlv_info info; - struct image_tlv tlv; + uint8_t hdr[IMAGE_HEADER_SIZE]; + uint8_t *ptr = hdr; struct stat st; int version; int padsize = 0; int i; - hdr = (struct image_header *)header_buffer; - if (argc != 4 && argc!=5) { fprintf(stderr, "Usage: %s image key.der fw_version [padsize]\n", argv[0]); exit(1); @@ -111,6 +108,7 @@ int main(int argc, char *argv[]) perror(signed_name); exit(2); } + key_fd = open(argv[2], O_RDONLY); if (key_fd < 0) { perror(argv[2]); @@ -139,16 +137,27 @@ int main(int argc, char *argv[]) perror(in_name); exit(2); } - memset(hdr, 0x00, IMAGE_FIRMWARE_OFFSET); - hdr->ih_magic = IMAGE_MAGIC; - hdr->ih_load_addr = FLASH_AREA_IMAGE_0_OFFSET + IMAGE_FIRMWARE_OFFSET; - hdr->ih_hdr_size = IMAGE_FIRMWARE_OFFSET; - hdr->ih_img_size = st.st_size; - hdr->ih_ver.iv_major = version; - hdr->ih_ver.iv_build_num = (uint32_t)(st.st_mtime); + memset(hdr, 0xFF, IMAGE_HEADER_SIZE); + *((uint32_t *)ptr) = WOLFBOOT_MAGIC; + ptr += (sizeof(uint32_t)); + *((uint32_t *)(ptr)) = st.st_size; + ptr += (sizeof(uint32_t)); + + ptr += (sizeof(uint16_t)); + *(ptr++) = HDR_VERSION; + *(ptr++) = 4; + *((uint32_t *)(ptr)) = version; + ptr += (sizeof(uint32_t)); + + ptr += (sizeof(uint16_t) + sizeof(uint32_t)); + *(ptr++) = HDR_TIMESTAMP; + *(ptr++) = 8; + *((uint64_t *)(ptr)) = st.st_mtime; + ptr += sizeof(uint64_t); + /* Sha256 */ - wc_Sha256Update(&sha, (uint8_t *)hdr, IMAGE_FIRMWARE_OFFSET); + wc_Sha256Update(&sha, hdr, ptr - hdr); while(1) { r = read(in_fd, shabuf, 32); if (r <= 0) @@ -161,8 +170,32 @@ int main(int argc, char *argv[]) wc_ed25519_sign_msg(shabuf, 32, signature, &outlen, &key); wc_Sha256Free(&sha); + + *(ptr++) = HDR_SHA256; + *(ptr++) = SHA256_DIGEST_SIZE; + memcpy(ptr, shabuf, SHA256_DIGEST_SIZE); + ptr += SHA256_DIGEST_SIZE; + + wc_InitSha256(&keyhash); + wc_Sha256Update(&keyhash, inkey + ED25519_KEY_SIZE, ED25519_KEY_SIZE); + wc_Sha256Final(&keyhash, shabuf); + *(ptr++) = HDR_PUBKEY; + *(ptr++) = SHA256_DIGEST_SIZE; + memcpy(ptr, shabuf, SHA256_DIGEST_SIZE); + wc_Sha256Free(&keyhash); + ptr += SHA256_DIGEST_SIZE; + + *(ptr++) = HDR_SIGNATURE; + *(ptr++) = ED25519_SIG_SIZE; + memcpy(ptr, signature, ED25519_SIG_SIZE); + ptr += ED25519_SIG_SIZE; + *(ptr++) = HDR_END; + + printf("\n\n"); + print_buf(hdr, IMAGE_HEADER_SIZE); + /* Write header */ - write(out_fd, hdr, IMAGE_FIRMWARE_OFFSET); + write(out_fd, hdr, IMAGE_HEADER_SIZE); /* Write image payload */ lseek(in_fd, 0, SEEK_SET); @@ -177,38 +210,6 @@ int main(int argc, char *argv[]) break; } - /* TLV INFO hdr */ - memset(&info, 0, sizeof(info)); - info.it_magic = IMAGE_TLV_INFO_MAGIC; - info.it_tlv_tot = sizeof(info) + 3 * sizeof(tlv) + 2 * SHA256_DIGEST_SIZE + ED25519_SIG_SIZE; - write(out_fd, &info, sizeof(info)); - - /* TLV 0: SHA DIGEST */ - memset(&tlv, 0, sizeof(tlv)); - tlv.it_type = IMAGE_TLV_SHA256; - tlv.it_len = SHA256_DIGEST_SIZE; - write(out_fd, &tlv, sizeof(tlv)); - write(out_fd, shabuf, SHA256_DIGEST_SIZE); - - /* TLV 1: KEYHASH */ - wc_InitSha256(&keyhash); - wc_Sha256Update(&keyhash, inkey + ED25519_KEY_SIZE, ED25519_KEY_SIZE); - wc_Sha256Final(&keyhash, shabuf); - memset(&tlv, 0, sizeof(tlv)); - tlv.it_type = IMAGE_TLV_KEYHASH; - tlv.it_len = SHA256_DIGEST_SIZE; - write(out_fd, &tlv, sizeof(tlv)); - write(out_fd, shabuf, SHA256_DIGEST_SIZE); - wc_Sha256Free(&keyhash); - - /* TLV 2: SIGNATURE */ - memset(&tlv, 0, sizeof(tlv)); - tlv.it_type = IMAGE_TLV_ED25519; - tlv.it_len = ED25519_SIG_SIZE; - write(out_fd, &tlv, sizeof(tlv)); - write(out_fd, signature, ED25519_SIG_SIZE); - close(out_fd); - /* Pad if needed */ r = stat(signed_name, &st); if ((r == 0) && st.st_size < padsize) {