Removed dependency on bootutil. Starting from a new clean-room update design

pull/1/head
Daniele Lacamera 2018-11-21 07:00:35 +01:00
parent 281b460131
commit 6b3dfe2e69
18 changed files with 15 additions and 3382 deletions

View File

@ -17,14 +17,11 @@ LSCRIPT:=hal/$(TARGET).ld
OBJS:= \
./hal/$(TARGET).o \
./lib/bootutil/src/loader.o \
./lib/bootutil/src/image_validate.o \
./lib/bootutil/src/bootutil_misc.o \
./src/loader.o \
./src/mem.o \
./src/keys.o \
./src/crypto.o \
./src/wolfboot.o \
./src/main.o \
./src/image.o \
./lib/wolfssl/wolfcrypt/src/sha256.o \
./lib/wolfssl/wolfcrypt/src/hash.o \
./lib/wolfssl/wolfcrypt/src/wolfmath.o \
@ -41,12 +38,12 @@ ifeq ($(SIGN),ED25519)
./lib/wolfssl/wolfcrypt/src/ed25519.o \
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
./src/ed25519_pub_key.o
CFLAGS+=-DBOOT_SIGN_ED25519
CFLAGS+=-DWOLFBOOT_SIGN_ED25519
endif
ifeq ($(SIGN),EC256)
OBJS+= ./ext/wolfssl/wolfcrypt/src/ecc.o
CFLAGS+=-DBOOT_SIGN_EC256
CFLAGS+=-DWOLFBOOT_SIGN_EC256
endif
ifeq ($(DEBUG),1)

22
NOTICE
View File

@ -1,22 +0,0 @@
wolfBoot - copyright (c) wolfSSL Inc.
wolfBoot is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2, as published by
the Free Software Foundation.
wolfBoot, wolfSSL (formerly known as CyaSSL) and wolfCrypt are either licensed for use
under the GPLv2 or a standard commercial license. For our users who cannot use
wolfSSL under GPLv2, a commercial license to wolfBoot, wolfSSL and wolfCrypt is available.
Please contact wolfSSL Inc. directly at:
Email: licensing@wolfssl.com
Phone: +1 425 245-8247
More information can be found on the wolfSSL website at www.wolfssl.com.
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/)
and previously released under the Apache License, Version 2.0.
Portions of this software were developed at
Runtime Inc, copyright 2015 and previously released under the the Apache License, Version 2.0.

View File

@ -2,8 +2,7 @@
wolfSSL Secure Bootloader
wolfBoot is a portable, OS-agnostic, secure bootloader solution for 32-bit microcontrollers,
relying on wolfCrypt for firmware authentication, and a modified version of
[mcuboot](https://www.mcuboot.com/)'s *bootutil* library to implement firmware upgrade mechanisms.
relying on wolfCrypt for firmware authentication, providing firmware upgrade mechanisms.
Due to the minimalist design of the bootloader and the tiny HAL API, wolfBoot is completely independent
from any OS or bare-metal application, and can be easily ported and integrated in existing embedded software
@ -32,8 +31,9 @@ with no dynamic memory allocation mechanism or linkage to any standard C library
The core application depends on the following libraries:
- wolfCrypt, which is used to verify the Ed25519 signature of the images
- A modified version of mcuboot's bootutil, to handle the firmware image slots and the upgrade state-machine
- A minimalist Hardware Abstraction Layer, with an implementation provided for the supported target, which is in charge for IAP flash access and clock setting on the specific MCU
- The core bootloader
- A small application library to interact with the bootloader
The goal of this application is to perform image verification and/or requested firmware upgrade tasks
before chain-loading the actual firmware from a specific location in flash.

View File

@ -4,7 +4,7 @@ In order to run wolfBoot on a target microcontroller, an implementation of the H
must be provided.
The HAL only purposes are allowing write/erase operations from the bootloader
and the application initiating the firmware upgrade through the bootutil library, and
and the application initiating the firmware upgrade through the application library, and
ensuring that the MCU is running at full speed during boot, to optimize the
verification of the signatures.

View File

@ -1,69 +0,0 @@
#ifndef H_BOOTUTIL_
#define H_BOOTUTIL_
#include <inttypes.h>
/** Attempt to boot the contents of slot 0. */
#define BOOT_SWAP_TYPE_NONE 1
/** Swap to slot 1. Absent a confirm command, revert back on next boot. */
#define BOOT_SWAP_TYPE_TEST 2
/** Swap to slot 1, and permanently switch to booting its contents. */
#define BOOT_SWAP_TYPE_PERM 3
/** Swap back to alternate slot. A confirm changes this state to NONE. */
#define BOOT_SWAP_TYPE_REVERT 4
/** Swap failed because image to be run is not valid */
#define BOOT_SWAP_TYPE_FAIL 5
/** Swapping encountered an unrecoverable error */
#define BOOT_SWAP_TYPE_PANIC 0xff
#define MAX_FLASH_ALIGN 8
#define BOOT_MAX_ALIGN MAX_FLASH_ALIGN
struct image_header;
/**
* A response object provided by the boot loader code; indicates where to jump
* to execute the main image.
*/
struct boot_rsp {
/** A pointer to the header of the image to be executed. */
const struct image_header *br_hdr;
/**
* The flash offset of the image to execute. Indicates the position of
* the image header within its flash device.
*/
uint8_t br_flash_dev_id;
uint32_t br_image_off;
};
/* This is not actually used by bootloader's code but can be used by apps
* when attempting to read/write a trailer.
*/
struct image_trailer {
uint8_t copy_done;
uint8_t pad1[MAX_FLASH_ALIGN - 1];
uint8_t image_ok;
uint8_t pad2[MAX_FLASH_ALIGN - 1];
uint8_t magic[16];
};
/* you must have pre-allocated all the entries within this structure */
int boot_go(struct boot_rsp *rsp);
int boot_swap_type(void);
int boot_set_pending(int permanent);
int boot_set_confirmed(void);
#define SPLIT_GO_OK (0)
#define SPLIT_GO_NON_MATCHING (-1)
#define SPLIT_GO_ERR (-2)
int
split_go(int loader_slot, int split_slot, void **entry);
#endif

View File

@ -1,136 +0,0 @@
/* flash_map.h
*
* 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
*/
#ifndef H_UTIL_FLASH_MAP_
#define H_UTIL_FLASH_MAP_
/**
*
* System will contain a map which contains flash areas. Every
* region will contain flash identifier, offset within flash and length.
*
* 1. This system map could be in a file within filesystem (Initializer
* must know/figure out where the filesystem is at).
* 2. Map could be at fixed location for project (compiled to code)
* 3. Map could be at specific place in flash (put in place at mfg time).
*
* Note that the map you use must be valid for BSP it's for,
* match the linker scripts when platform executes from flash,
* and match the target offset specified in download script.
*/
#include <inttypes.h>
/**
* @brief Structure describing an area on a flash device.
*
* Multiple flash devices may be available in the system, each of
* which may have its own areas. For this reason, flash areas track
* which flash device they are part of.
*/
struct flash_area {
/**
* This flash area's ID; unique in the system.
*/
uint8_t fa_id;
/**
* ID of the flash device this area is a part of.
*/
uint8_t fa_device_id;
uint16_t pad16;
/**
* This area's offset, relative to the beginning of its flash
* device's storage.
*/
uint32_t fa_off;
/**
* This area's size, in bytes.
*/
uint32_t fa_size;
};
/**
* @brief Structure describing a sector within a flash area.
*
* Each sector has an offset relative to the start of its flash area
* (NOT relative to the start of its flash device), and a size. A
* flash area may contain sectors with different sizes.
*/
struct flash_sector {
/**
* Offset of this sector, from the start of its flash area (not device).
*/
uint32_t fs_off;
/**
* Size of this sector, in bytes.
*/
uint32_t fs_size;
};
/*
* Retrieve a memory-mapped flash device's base address.
*
* On success, the address will be stored in the value pointed to by
* ret.
*
* Returns 0 on success, or an error code on failure.
*/
int flash_device_base(uint8_t fd_id, uintptr_t *ret);
/*
* Start using flash area.
*/
int flash_area_open(uint8_t id, const struct flash_area **);
void flash_area_close(const struct flash_area *);
/*
* Read/write/erase. Offset is relative from beginning of flash area.
*/
int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
uint32_t len);
int flash_area_write(const struct flash_area *, uint32_t off, const void *src,
uint32_t len);
int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
/*
* Alignment restriction for flash writes.
*/
uint8_t flash_area_align(const struct flash_area *);
/*
* Given flash area ID, return info about sectors within the area.
*/
int flash_area_get_sectors(int fa_id, uint32_t *count,
struct flash_sector *sectors);
int flash_area_id_from_image_slot(int slot);
int flash_area_id_to_image_slot(int area_id);
/* Get the build number of the image stored at the begining of the given flash area */
uint32_t flash_area_get_image_buildnum(const struct flash_area *fap);
#endif /* H_UTIL_FLASH_MAP_ */

View File

@ -1,30 +1,16 @@
#ifndef H_TARGETS_TARGET_
#define H_TARGETS_TARGET_
#define FLASH_DEV_NAME "flash"
#define FLASH_ALIGN 4
/* Example flash partitioning.
* Ensure that your firmware entry point is
* at FLASH_AREA_IMAGE_0_OFFSET + 0x100
*/
#define FLASH_AREA_IMAGE_0_OFFSET 0x20000
#define FLASH_AREA_IMAGE_0_SIZE 0x20000
#define FLASH_AREA_IMAGE_1_OFFSET 0x40000
#define FLASH_AREA_IMAGE_1_SIZE 0x20000
#define FLASH_AREA_IMAGE_SCRATCH_OFFSET 0x60000
#define FLASH_AREA_IMAGE_SCRATCH_SIZE 0x20000
#define WOLFBOOT_SECTOR_SIZE 0x20000
#define WOLFBOOT_PARTITION_SIZE 0x20000
/*
* Sanity check the target support.
*/
#if !defined(FLASH_DEV_NAME) || \
!defined(FLASH_ALIGN) || \
!defined(FLASH_AREA_IMAGE_0_OFFSET) || \
!defined(FLASH_AREA_IMAGE_0_SIZE) || \
!defined(FLASH_AREA_IMAGE_1_OFFSET) || \
!defined(FLASH_AREA_IMAGE_1_SIZE)
#error "Target support is incomplete; cannot build wolfboot."
#endif
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x20000
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x40000
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x60000
#endif

View File

@ -1,88 +0,0 @@
#ifndef H_IMAGE_
#define H_IMAGE_
#include <inttypes.h>
struct flash_area;
#define IMAGE_MAGIC 0x96f3b83d
#define IMAGE_MAGIC_V1 0x96f3b83c
#define IMAGE_MAGIC_NONE 0xffffffff
#define IMAGE_TLV_INFO_MAGIC 0x6907
#define IMAGE_HEADER_SIZE 32
#define PACKED __attribute__((packed))
/*
* Image header flags.
*/
#define IMAGE_F_PIC 0x00000001 /* Not supported. */
#define IMAGE_F_NON_BOOTABLE 0x00000010 /* Split image app. */
/*
* Indicates that this image should be loaded into RAM instead of run
* directly from flash. The address to load should be in the
* ih_load_addr field of the header.
*/
#define IMAGE_F_RAM_LOAD 0x00000020
/*
* ECSDA224 is with NIST P-224
* ECSDA256 is with NIST P-256
*/
/*
* Image trailer TLV types.
*
* Signature is generated by computing signature over the image hash.
* Currently the only image hash type is SHA256.
*
* Signature comes in the form of 2 TLVs.
* 1st on identifies the public key which should be used to verify it.
* 2nd one is the actual signature.
*/
#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */
#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */
#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */
#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output */
#define IMAGE_TLV_ECDSA256 0x22 /* ECDSA of hash output */
#define IMAGE_TLV_ED25519 0x23 /* ED25519 of hash output */
struct PACKED image_version {
uint8_t iv_major;
uint8_t iv_minor;
uint16_t iv_revision;
uint32_t iv_build_num;
};
/** Image header. All fields are in little endian byte order. */
struct PACKED image_header {
uint32_t ih_magic;
uint32_t ih_load_addr;
uint16_t ih_hdr_size; /* Size of image header (bytes). */
uint16_t _pad1;
uint32_t ih_img_size; /* Does not include header. */
uint32_t ih_flags; /* IMAGE_F_[...]. */
struct image_version ih_ver;
uint32_t _pad2;
};
/** Image TLV header. All fields in little endian. */
struct PACKED image_tlv_info {
uint16_t it_magic;
uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */
};
/** Image trailer TLV format. All fields in little endian. */
struct PACKED image_tlv {
uint8_t it_type; /* IMAGE_TLV_[...]. */
uint8_t _pad;
uint16_t it_len; /* Data length (not including TLV header). */
};
int bootutil_img_validate(struct image_header *hdr,
const struct flash_area *fap,
uint8_t *tmp_buf, uint32_t tmp_buf_sz,
uint8_t *seed, int seed_len, uint8_t *out_hash);
#endif

View File

@ -1,14 +0,0 @@
#ifndef __BOOTUTIL_SIGN_KEY_H_
#define __BOOTUTIL_SIGN_KEY_H_
#include <stdint.h>
struct bootutil_key {
const uint8_t *key;
const unsigned int *len;
};
extern const struct bootutil_key bootutil_keys[];
extern const int bootutil_key_cnt;
#endif /* __BOOTUTIL_SIGN_KEY_H_ */

View File

@ -1,801 +0,0 @@
/* bootutil_misc.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
*
* **** This file incorporates work covered by the following copyright and ****
* **** permission notice: ****
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
#include <string.h>
#include <inttypes.h>
#include <stddef.h>
#include "hal.h"
#include "printf.h"
#include "bootutil/image.h"
#include "bootutil_priv.h"
#include "bootutil.h"
#include "target.h"
struct area {
struct flash_area whole;
struct flash_area *areas;
uint32_t num_areas;
uint8_t id;
};
struct area_desc {
struct area slots[3];
uint32_t num_slots;
};
static struct area_desc flash_areas[1] = {
{
.slots = {
{
.whole = {
.fa_id = FLASH_AREA_IMAGE_0,
.fa_device_id = 0,
.fa_off = FLASH_AREA_IMAGE_0_OFFSET,
.fa_size = FLASH_AREA_IMAGE_0_SIZE,
},
.id = FLASH_AREA_IMAGE_0,
.num_areas = 1
},
{
.whole = {
.fa_id = FLASH_AREA_IMAGE_1,
.fa_device_id = 0,
.fa_off = FLASH_AREA_IMAGE_1_OFFSET,
.fa_size = FLASH_AREA_IMAGE_1_SIZE,
},
.id = FLASH_AREA_IMAGE_1,
.num_areas = 1
},
#ifndef WOLFBOOT_OVERWRITE_ONLY
{
.whole = {
.fa_id = FLASH_AREA_IMAGE_SCRATCH,
.fa_device_id = 0,
.fa_off = FLASH_AREA_IMAGE_SCRATCH_OFFSET,
.fa_size = FLASH_AREA_IMAGE_SCRATCH_SIZE,
},
.id = FLASH_AREA_IMAGE_SCRATCH,
.num_areas = 1
}
},
.num_slots = 3
#else
},
.num_slots = 2
#endif
}
} ;
void boot_panic(void)
{
while(1)
;
}
void boot_panic_unless(int x)
{
if(!x)
while(1);
}
int boot_current_slot;
const uint32_t boot_img_magic[] = {
0xf395c277,
0x7fefd260,
0x0f505235,
0x8079b62c,
};
#define BOOT_MAGIC_SZ (sizeof(boot_img_magic))
#define BOOT_MAGIC_ARR_SZ (sizeof(boot_img_magic) / sizeof (uint32_t))
struct boot_swap_table {
/** * For each field, a value of 0 means "any". */
uint8_t magic_slot0;
uint8_t magic_slot1;
uint8_t image_ok_slot0;
uint8_t image_ok_slot1;
uint8_t copy_done_slot0;
uint8_t swap_type;
};
/**
* This set of tables maps image trailer contents to swap operation type.
* When searching for a match, these tables must be iterated sequentially.
*
* NOTE: the table order is very important. The settings in Slot 1 always
* are priority to Slot 0 and should be located earlier in the table.
*
* The table lists only states where there is action needs to be taken by
* the bootloader, as in starting/finishing a swap operation.
*/
static const struct boot_swap_table boot_swap_tables[] = {
{
.magic_slot0 = 0,
.magic_slot1 = BOOT_MAGIC_GOOD,
.image_ok_slot0 = 0,
.image_ok_slot1 = 0xff,
.copy_done_slot0 = 0,
.swap_type = BOOT_SWAP_TYPE_TEST,
},
{
.magic_slot0 = 0,
.magic_slot1 = BOOT_MAGIC_GOOD,
.image_ok_slot0 = 0,
.image_ok_slot1 = 0x01,
.copy_done_slot0 = 0,
.swap_type = BOOT_SWAP_TYPE_PERM,
},
{
.magic_slot0 = BOOT_MAGIC_GOOD,
.magic_slot1 = BOOT_MAGIC_UNSET,
.image_ok_slot0 = 0xff,
.image_ok_slot1 = 0,
.copy_done_slot0 = 0x01,
.swap_type = BOOT_SWAP_TYPE_REVERT,
},
};
#define BOOT_SWAP_TABLES_COUNT \
(sizeof boot_swap_tables / sizeof boot_swap_tables[0])
int
boot_magic_code(const uint32_t *magic)
{
size_t i;
if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
return BOOT_MAGIC_GOOD;
}
for (i = 0; i < BOOT_MAGIC_SZ / sizeof *magic; i++) {
if (magic[i] != 0xffffffff) {
return BOOT_MAGIC_BAD;
}
}
return BOOT_MAGIC_UNSET;
}
uint32_t
boot_slots_trailer_sz(uint8_t min_write_sz)
{
return /* state for all sectors */
BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */ +
BOOT_MAGIC_SZ;
}
static uint32_t
boot_scratch_trailer_sz(uint8_t min_write_sz)
{
return BOOT_STATUS_STATE_COUNT * min_write_sz + /* state for one sector */
BOOT_MAX_ALIGN * 2 + /* image_ok + swap_size */
BOOT_MAGIC_SZ;
}
static uint32_t
boot_magic_off(const struct flash_area *fap)
{
boot_panic_unless(offsetof(struct image_trailer, magic) == 16);
return fap->fa_size - BOOT_MAGIC_SZ;
}
int
boot_status_entries(const struct flash_area *fap)
{
switch (fap->fa_id) {
case FLASH_AREA_IMAGE_0:
case FLASH_AREA_IMAGE_1:
return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
case FLASH_AREA_IMAGE_SCRATCH:
return BOOT_STATUS_STATE_COUNT;
default:
return BOOT_EBADARGS;
}
}
uint32_t
boot_status_off(const struct flash_area *fap)
{
uint32_t off_from_end;
uint8_t elem_sz;
elem_sz = flash_area_align(fap);
if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
off_from_end = boot_scratch_trailer_sz(elem_sz);
} else {
off_from_end = boot_slots_trailer_sz(elem_sz);
}
boot_panic_unless(off_from_end <= fap->fa_size);
return fap->fa_size - off_from_end;
}
static uint32_t
boot_copy_done_off(const struct flash_area *fap)
{
boot_panic_unless(fap->fa_id != FLASH_AREA_IMAGE_SCRATCH);
boot_panic_unless(offsetof(struct image_trailer, copy_done) == 0);
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
}
static uint32_t
boot_image_ok_off(const struct flash_area *fap)
{
boot_panic_unless(offsetof(struct image_trailer, image_ok) == 8);
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
}
static uint32_t
boot_swap_size_off(const struct flash_area *fap)
{
/*
* The "swap_size" field if located just before the trailer.
* The scratch slot doesn't store "copy_done"...
*/
if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
}
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
}
int
boot_read_swap_state(const struct flash_area *fap,
struct boot_swap_state *state)
{
uint32_t magic[BOOT_MAGIC_ARR_SZ];
uint32_t off;
int rc;
off = boot_magic_off(fap);
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
if (rc != 0) {
return BOOT_EFLASH;
}
state->magic = boot_magic_code(magic);
if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
off = boot_copy_done_off(fap);
rc = flash_area_read(fap, off, &state->copy_done, sizeof state->copy_done);
if (rc != 0) {
return BOOT_EFLASH;
}
}
off = boot_image_ok_off(fap);
rc = flash_area_read(fap, off, &state->image_ok, sizeof state->image_ok);
if (rc != 0) {
return BOOT_EFLASH;
}
return 0;
}
/**
* Reads the image trailer from the scratch area.
*/
int
boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
{
const struct flash_area *fap;
int rc;
switch (flash_area_id) {
case FLASH_AREA_IMAGE_SCRATCH:
case FLASH_AREA_IMAGE_0:
case FLASH_AREA_IMAGE_1:
rc = flash_area_open(flash_area_id, &fap);
if (rc != 0) {
return BOOT_EFLASH;
}
break;
default:
return BOOT_EBADARGS;
}
rc = boot_read_swap_state(fap, state);
flash_area_close(fap);
return rc;
}
int
boot_read_swap_size(uint32_t *swap_size)
{
uint32_t magic[BOOT_MAGIC_ARR_SZ];
uint32_t off;
const struct flash_area *fap;
int rc;
/*
* In the middle a swap, tries to locate the saved swap size. Looks
* for a valid magic, first on Slot 0, then on scratch. Both "slots"
* can end up being temporary storage for a swap and it is assumed
* that if magic is valid then swap size is too, because magic is
* always written in the last step.
*/
rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
if (rc != 0) {
return BOOT_EFLASH;
}
off = boot_magic_off(fap);
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
if (rc != 0) {
rc = BOOT_EFLASH;
goto out;
}
if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
/*
* If Slot 0 's magic is not valid, try scratch...
*/
flash_area_close(fap);
rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
if (rc != 0) {
return BOOT_EFLASH;
}
off = boot_magic_off(fap);
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
if (rc != 0) {
rc = BOOT_EFLASH;
goto out;
}
boot_panic_unless(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
}
off = boot_swap_size_off(fap);
rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
if (rc != 0) {
rc = BOOT_EFLASH;
}
out:
flash_area_close(fap);
return rc;
}
int
boot_write_magic(const struct flash_area *fap)
{
uint32_t off;
int rc;
off = boot_magic_off(fap);
rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
if (rc != 0) {
return BOOT_EFLASH;
}
return 0;
}
static int
boot_write_flag(int flag, const struct flash_area *fap)
{
uint32_t off;
int rc;
uint8_t buf[BOOT_MAX_ALIGN];
uint8_t align;
switch (flag) {
case BOOT_FLAG_COPY_DONE:
off = boot_copy_done_off(fap);
break;
case BOOT_FLAG_IMAGE_OK:
off = boot_image_ok_off(fap);
break;
default:
return BOOT_EBADARGS;
}
align = flash_area_align(fap);
boot_panic_unless(align <= BOOT_MAX_ALIGN);
memset(buf, 0xFF, BOOT_MAX_ALIGN);
buf[0] = BOOT_FLAG_SET;
rc = flash_area_write(fap, off, buf, align);
if (rc != 0) {
return BOOT_EFLASH;
}
return 0;
}
int
boot_write_copy_done(const struct flash_area *fap)
{
return boot_write_flag(BOOT_FLAG_COPY_DONE, fap);
}
int
boot_write_image_ok(const struct flash_area *fap)
{
return boot_write_flag(BOOT_FLAG_IMAGE_OK, fap);
}
int
boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
{
uint32_t off;
int rc;
uint8_t buf[BOOT_MAX_ALIGN];
uint8_t align;
off = boot_swap_size_off(fap);
align = flash_area_align(fap);
boot_panic_unless(align <= BOOT_MAX_ALIGN);
if (align < sizeof swap_size) {
align = sizeof swap_size;
}
memset(buf, 0xFF, BOOT_MAX_ALIGN);
memcpy(buf, (uint8_t *)&swap_size, sizeof swap_size);
rc = flash_area_write(fap, off, buf, align);
if (rc != 0) {
return BOOT_EFLASH;
}
return 0;
}
int
boot_swap_type(void)
{
const struct boot_swap_table *table;
struct boot_swap_state slot0;
struct boot_swap_state slot1;
int rc;
size_t i;
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &slot0);
if (rc) {
return BOOT_SWAP_TYPE_PANIC;
}
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &slot1);
if (rc) {
return BOOT_SWAP_TYPE_PANIC;
}
for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
table = boot_swap_tables + i;
if ((!table->magic_slot0 || table->magic_slot0 == slot0.magic ) &&
(!table->magic_slot1 || table->magic_slot1 == slot1.magic ) &&
(!table->image_ok_slot0 || table->image_ok_slot0 == slot0.image_ok ) &&
(!table->image_ok_slot1 || table->image_ok_slot1 == slot1.image_ok ) &&
(!table->copy_done_slot0 || table->copy_done_slot0 == slot0.copy_done)) {
wolfBoot_printf("Swap type: %s",
table->swap_type == BOOT_SWAP_TYPE_TEST ? "test" :
table->swap_type == BOOT_SWAP_TYPE_PERM ? "perm" :
table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
"BUG; can't happen");
boot_panic_unless(table->swap_type == BOOT_SWAP_TYPE_TEST ||
table->swap_type == BOOT_SWAP_TYPE_PERM ||
table->swap_type == BOOT_SWAP_TYPE_REVERT);
return table->swap_type;
}
}
wolfBoot_printf("Swap type: none");
return BOOT_SWAP_TYPE_NONE;
}
/**
* Marks the image in slot 1 as pending. On the next reboot, the system will
* perform a one-time boot of the slot 1 image.
*
* @param permanent Whether the image should be used permanently or
* only tested once:
* 0=run image once, then confirm or revert.
* 1=run image forever.
*
* @return 0 on success; nonzero on failure.
*/
int
boot_set_pending(int permanent)
{
const struct flash_area *fap;
struct boot_swap_state state_slot1;
int rc;
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &state_slot1);
if (rc != 0) {
return rc;
}
switch (state_slot1.magic) {
case BOOT_MAGIC_GOOD:
/* Swap already scheduled. */
return 0;
case BOOT_MAGIC_UNSET:
rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
if (rc != 0) {
rc = BOOT_EFLASH;
} else {
rc = boot_write_magic(fap);
}
if (rc == 0 && permanent) {
rc = boot_write_image_ok(fap);
}
flash_area_close(fap);
return rc;
default:
/* XXX: Temporary boot_panic_unless. */
boot_panic_unless(0);
return -1;
}
}
/**
* Marks the image in slot 0 as confirmed. The system will continue booting into the image in slot 0 until told to boot from a different slot.
*
* @return 0 on success; nonzero on failure.
*/
int
boot_set_confirmed(void)
{
const struct flash_area *fap;
struct boot_swap_state state_slot0;
int rc;
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
if (rc != 0) {
return rc;
}
switch (state_slot0.magic) {
case BOOT_MAGIC_GOOD:
/* Confirm needed; proceed. */
break;
case BOOT_MAGIC_UNSET:
/* Already confirmed. */
return 0;
case BOOT_MAGIC_BAD:
/* Unexpected state. */
return BOOT_EBADVECT;
}
if (state_slot0.copy_done == BOOT_FLAG_UNSET) {
/* Swap never completed. This is unexpected. */
return BOOT_EBADVECT;
}
if (state_slot0.image_ok != BOOT_FLAG_UNSET) {
/* Already confirmed. */
return 0;
}
rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
if (rc) {
rc = BOOT_EFLASH;
goto done;
}
rc = boot_write_image_ok(fap);
if (rc != 0) {
goto done;
}
rc = 0;
done:
flash_area_close(fap);
return rc;
}
uint8_t flash_area_align(const struct flash_area *area)
{
(void)area;
return 1;
}
int flash_area_open(uint8_t id, const struct flash_area **area)
{
uint32_t i;
for (i = 0; i < flash_areas->num_slots; i++) {
if (flash_areas->slots[i].id == id)
break;
}
if (i == flash_areas->num_slots) {
wolfBoot_printf("Unsupported area\n");
boot_panic();
}
*area = &flash_areas->slots[i].whole;
return 0;
}
void flash_area_close(const struct flash_area *area)
{
(void)area;
}
/*
* Read/write/erase. Offset is relative from beginning of flash area.
*/
int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
uint32_t len)
{
unsigned int i;
uint8_t *src8, *dst8;
wolfBoot_printf("%s: area=%d, off=%x, len=%x",
__func__, area->fa_id, off, len);
if (!area)
return -1;
if ((off + len) > (area->fa_size))
return -1;
src8 = (uint8_t *)(area->fa_off + off);
dst8 = (uint8_t *)dst;
for (i = 0; i < len; i++) {
dst8[i] = src8[i];
}
return 0;
}
int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
uint32_t len)
{
wolfBoot_printf("%s: area=%d, off=%x, len=%x", __func__,
area->fa_id, off, len);
hal_flash_unlock();
hal_flash_write(area->fa_off + off, src, len);
hal_flash_lock();
return 0;
}
int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
{
wolfBoot_printf("%s: area=%d, off=%x, len=%x", __func__,
area->fa_id, off, len);
hal_flash_unlock();
hal_flash_erase(area->fa_off + off, len);
hal_flash_lock();
return 0;
}
int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
{
uint32_t i;
struct area *slot;
for (i = 0; i < flash_areas->num_slots; i++) {
if (flash_areas->slots[i].id == idx)
break;
}
if (i == flash_areas->num_slots) {
wolfBoot_printf("Unsupported area\n");
boot_panic();
}
slot = &flash_areas->slots[i];
if (slot->num_areas > (uint32_t)*cnt) {
wolfBoot_printf("Too many areas in slot\n");
boot_panic();
}
if (slot->num_areas == 1) {
slot->areas = &slot->whole;
}
*cnt = slot->num_areas;
memcpy(ret, slot->areas, slot->num_areas * sizeof(struct flash_area));
return 0;
}
int flash_area_get_sectors(int fa_id, uint32_t *count,
struct flash_sector *sectors)
{
uint32_t i;
struct area *slot;
for (i = 0; i < flash_areas->num_slots; i++) {
if (flash_areas->slots[i].id == fa_id)
break;
}
if (i == flash_areas->num_slots) {
wolfBoot_printf("Unsupported area\n");
boot_panic();
}
slot = &flash_areas->slots[i];
if (slot->num_areas > *count) {
wolfBoot_printf("Too many areas in slot\n");
boot_panic();
}
*count = slot->num_areas;
if (slot->num_areas == 1) {
sectors[0].fs_off = slot->whole.fa_off;
sectors[0].fs_size = slot->whole.fa_size;
} else {
for (i = 0; i < slot->num_areas; i++) {
sectors[i].fs_off = slot->areas[i].fa_off -
slot->whole.fa_off;
sectors[i].fs_size = slot->areas[i].fa_size;
}
}
return 0;
}
int flash_area_id_from_image_slot(int slot)
{
return slot + FLASH_AREA_IMAGE_0;
}
uint8_t flash_area_erased_val(const struct flash_area *fap)
{
(void)fap;
return 0xff;
}
uint32_t flash_area_get_image_buildnum(const struct flash_area *fap)
{
struct image_header *hdr = (struct image_header *)(fap->fa_off);
return hdr->ih_ver.iv_build_num;
}

View File

@ -1,251 +0,0 @@
/* bootutil_priv.h
*
* 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
*/
#ifndef H_BOOTUTIL_PRIV_
#define H_BOOTUTIL_PRIV_
#include "flash_map_backend.h"
#include "bootutil/image.h"
#ifndef BOOT_MAX_IMG_SECTORS
# define BOOT_MAX_IMG_SECTORS (32)
#endif
extern void boot_panic(void);
extern void boot_panic_unless(int x);
#define FLASH_AREA_IMAGE_0 1
#define FLASH_AREA_IMAGE_1 2
#define FLASH_AREA_IMAGE_SCRATCH 3
struct flash_area;
#define BOOT_EFLASH 1
#define BOOT_EFILE 2
#define BOOT_EBADIMAGE 3
#define BOOT_EBADVECT 4
#define BOOT_EBADSTATUS 5
#define BOOT_ENOMEM 6
#define BOOT_EBADARGS 7
#define BOOT_TMPBUF_SZ 256
/*
* Maintain state of copy progress.
*/
struct boot_status {
uint32_t idx; /* Which area we're operating on */
uint8_t state; /* Which part of the swapping process are we at */
uint8_t use_scratch; /* Are status bytes ever written to scratch? */
uint32_t swap_size; /* Total size of swapped image */
};
#define BOOT_MAGIC_GOOD 1
#define BOOT_MAGIC_BAD 2
#define BOOT_MAGIC_UNSET 3
/**
* End-of-image slot structure.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* ~ ~
* ~ Swap status (variable, aligned) ~
* ~ ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Swap size |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* ~ 0xff padding (MAX ALIGN - 4) ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Copy done | 0xff padding (MAX ALIGN - 1) ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Image OK | 0xff padding (MAX ALIGN - 1) ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* ~ MAGIC (16 octets) ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
extern const uint32_t boot_img_magic[4];
struct boot_swap_state {
uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */
uint8_t copy_done;
uint8_t image_ok;
};
/*
* The current flashmap API does not check the amount of space allocated when
* loading sector data from the flash device, allowing for smaller counts here
* would most surely incur in overruns.
*
* TODO: make flashmap API receive the current sector array size.
*/
#if BOOT_MAX_IMG_SECTORS < 32
#error "Too few sectors, please increase BOOT_MAX_IMG_SECTORS to at least 32"
#endif
/** Number of image slots in flash; currently limited to two. */
#define BOOT_NUM_SLOTS 2
/** Maximum number of image sectors supported by the bootloader. */
#define BOOT_STATUS_STATE_COUNT 3
#define BOOT_STATUS_MAX_ENTRIES BOOT_MAX_IMG_SECTORS
#define BOOT_STATUS_SOURCE_NONE 0
#define BOOT_STATUS_SOURCE_SCRATCH 1
#define BOOT_STATUS_SOURCE_SLOT0 2
#define BOOT_FLAG_IMAGE_OK 0
#define BOOT_FLAG_COPY_DONE 1
#define BOOT_FLAG_SET 0x01
#define BOOT_FLAG_UNSET 0xff
extern const uint32_t BOOT_MAGIC_SZ;
/**
* Compatibility shim for flash sector type.
*
* This can be deleted when flash_area_to_sectors() is removed.
*/
typedef struct flash_sector boot_sector_t;
/** Private state maintained during boot. */
struct boot_loader_state {
struct {
struct image_header hdr;
const struct flash_area *area;
boot_sector_t *sectors;
size_t num_sectors;
} imgs[BOOT_NUM_SLOTS];
const struct flash_area *scratch_area;
uint8_t write_sz;
};
int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
size_t slen, uint8_t key_id);
uint32_t boot_slots_trailer_sz(uint8_t min_write_sz);
int boot_status_entries(const struct flash_area *fap);
uint32_t boot_status_off(const struct flash_area *fap);
int boot_read_swap_state(const struct flash_area *fap,
struct boot_swap_state *state);
int boot_read_swap_state_by_id(int flash_area_id,
struct boot_swap_state *state);
int boot_write_magic(const struct flash_area *fap);
int boot_write_status(struct boot_status *bs);
int boot_schedule_test_swap(void);
int boot_write_copy_done(const struct flash_area *fap);
int boot_write_image_ok(const struct flash_area *fap);
int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
int boot_read_swap_size(uint32_t *swap_size);
/*
* Accessors for the contents of struct boot_loader_state.
*/
/* These are macros so they can be used as lvalues. */
#define BOOT_IMG_AREA(state, slot) ((state)->imgs[(slot)].area)
#define BOOT_SCRATCH_AREA(state) ((state)->scratch_area)
#define BOOT_WRITE_SZ(state) ((state)->write_sz)
static inline struct image_header*
boot_img_hdr(struct boot_loader_state *state, size_t slot)
{
return &state->imgs[slot].hdr;
}
static inline size_t
boot_img_num_sectors(struct boot_loader_state *state, size_t slot)
{
return state->imgs[slot].num_sectors;
}
/*
* Offset of the slot from the beginning of the flash device.
*/
static inline uint32_t
boot_img_slot_off(struct boot_loader_state *state, size_t slot)
{
return state->imgs[slot].area->fa_off;
}
static inline size_t boot_scratch_area_size(struct boot_loader_state *state)
{
return state->scratch_area->fa_size;
}
static inline size_t
boot_img_sector_size(struct boot_loader_state *state,
size_t slot, size_t sector)
{
return state->imgs[slot].sectors[sector].fs_size;
}
static inline uint32_t
boot_img_sector_off(struct boot_loader_state *state, size_t slot,
size_t sector)
{
return state->imgs[slot].sectors[sector].fs_off -
state->imgs[slot].sectors[0].fs_off;
}
static inline int
boot_initialize_area(struct boot_loader_state *state, int flash_area)
{
uint32_t num_sectors;
struct flash_sector *out_sectors;
size_t *out_num_sectors;
int rc;
switch (flash_area) {
case FLASH_AREA_IMAGE_0:
num_sectors = BOOT_MAX_IMG_SECTORS;
out_sectors = state->imgs[0].sectors;
out_num_sectors = &state->imgs[0].num_sectors;
break;
case FLASH_AREA_IMAGE_1:
num_sectors = BOOT_MAX_IMG_SECTORS;
out_sectors = state->imgs[1].sectors;
out_num_sectors = &state->imgs[1].num_sectors;
break;
default:
return -1;
}
rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
if (rc != 0) {
return rc;
}
*out_num_sectors = num_sectors;
return 0;
}
#endif

View File

@ -1,75 +0,0 @@
/* flash_map_backend.h
*
* 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
*/
#ifndef __FLASH_MAP_BACKEND_H__
#define __FLASH_MAP_BACKEND_H__
#include "flash.h"
/**
*
* Provides abstraction of flash regions for type of use.
* I.e. dude where's my image?
*
* System will contain a map which contains flash areas. Every
* region will contain flash identifier, offset within flash and length.
*
* 1. This system map could be in a file within filesystem (Initializer
* must know/figure out where the filesystem is at).
* 2. Map could be at fixed location for project (compiled to code)
* 3. Map could be at specific place in flash (put in place at mfg time).
*
* Note that the map you use must be valid for BSP it's for,
* match the linker scripts when platform executes from flash,
* and match the target offset specified in download script.
*/
#include <inttypes.h>
#include <sys/types.h>
/* Retrieve the flash device with the given name.
*
* Returns the flash device on success, or NULL on failure.
*/
struct device *flash_device_get_binding(char *dev_name);
/*
* Retrieve a memory-mapped flash device's base address.
*
* On success, the address will be stored in the value pointed to by
* ret.
*
* Returns 0 on success, or an error code on failure.
*/
int flash_device_base(uint8_t fd_id, uintptr_t *ret);
int flash_area_id_from_image_slot(int slot);
/* Retrieve the flash sector a given offset belongs to.
*
* Returns 0 on success, or an error code on failure.
*/
int flash_area_sector_from_off(off_t off, struct flash_sector *sector);
uint8_t flash_area_erased_val(const struct flash_area *fap);
#endif /* __FLASH_MAP_BACKEND_H__ */

View File

@ -1,273 +0,0 @@
/* image_validate.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
*
* **** This file incorporates work covered by the following copyright and ****
* **** permission notice: ****
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stddef.h>
#include <inttypes.h>
#include <string.h>
#include "hal.h"
#include "bootutil/image.h"
#include "bootutil/sign_key.h"
#include "wolfssl/wolfcrypt/sha256.h"
#include "wolfssl/ssl.h"
#include "bootutil_priv.h"
/*
* Compute SHA256 over the image.
*/
static int
bootutil_img_hash(struct image_header *hdr, const struct flash_area *fap,
uint8_t *tmp_buf, uint32_t tmp_buf_sz,
uint8_t *hash_result, uint8_t *seed, int seed_len)
{
wc_Sha256 sha256_ctx;
uint32_t blk_sz;
uint32_t size;
uint32_t off;
int rc;
wc_InitSha256(&sha256_ctx);
/* in some cases (split image) the hash is seeded with data from
* the loader image */
if (seed && (seed_len > 0)) {
wc_Sha256Update(&sha256_ctx, seed, seed_len);
}
/*
* Hash is computed over image header and image itself. No TLV is
* included ATM.
*/
size = hdr->ih_img_size + hdr->ih_hdr_size;
for (off = 0; off < size; off += blk_sz) {
blk_sz = size - off;
if (blk_sz > tmp_buf_sz) {
blk_sz = tmp_buf_sz;
}
rc = flash_area_read(fap, off, tmp_buf, blk_sz);
if (rc) {
return rc;
}
wc_Sha256Update(&sha256_ctx, tmp_buf, blk_sz);
}
wc_Sha256Final(&sha256_ctx, hash_result);
return 0;
}
/*
* Currently, we only support being able to verify one type of
* signature, because there is a single verification function that we
* call. List the type of TLV we are expecting. If we aren't
* configured for any signature, don't define this macro.
*/
#if defined(BOOT_SIGN_RSA)
# define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS
# define EXPECTED_SIG_LEN(x) ((x) == 256) /* 2048 bits */
# if defined(BOOT_SIGN_EC) || defined(BOOT_SIGN_EC256)
# error "Multiple signature types not yet supported"
# endif
#elif defined(BOOT_SIGN_EC)
# define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA224
# define EXPECTED_SIG_LEN(x) ((x) >= 64) /* oids + 2 * 28 bytes */
# if defined(BOOT_SIGN_EC256)
# error "Multiple signature types not yet supported"
# endif
#elif defined(BOOT_SIGN_EC256)
# define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA256
# define EXPECTED_SIG_LEN(x) ((x) >= 72) /* oids + 2 * 32 bytes */
#elif defined(BOOT_SIGN_ED25519)
# define EXPECTED_SIG_TLV IMAGE_TLV_ED25519
# define EXPECTED_SIG_LEN(x) ((x) == 64)
#endif
#ifdef EXPECTED_SIG_TLV
extern void boot_panic_unless(int);
static int
bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
{
wc_Sha256 sha256_ctx;
int i;
const struct bootutil_key *key;
uint8_t hash[32];
boot_panic_unless(keyhash_len <= 32);
for (i = 0; i < bootutil_key_cnt; i++) {
key = &bootutil_keys[i];
wc_InitSha256(&sha256_ctx);
wc_Sha256Update(&sha256_ctx, key->key, *key->len);
wc_Sha256Final(&sha256_ctx, hash);
if (!memcmp(hash, keyhash, keyhash_len)) {
return i;
}
}
return -1;
}
#endif
/*
* Verify the integrity of the image.
* Return non-zero if image could not be validated/does not validate.
*/
int
bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap,
uint8_t *tmp_buf, uint32_t tmp_buf_sz,
uint8_t *seed, int seed_len, uint8_t *out_hash)
{
uint32_t off;
uint32_t end;
int sha256_valid = 0;
struct image_tlv_info info;
#ifdef EXPECTED_SIG_TLV
int valid_signature = 0;
int key_id = -1;
#endif
struct image_tlv tlv;
uint8_t buf[256];
uint8_t hash[32];
int rc;
rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash,
seed, seed_len);
if (rc) {
return rc;
}
if (out_hash) {
memcpy(out_hash, hash, 32);
}
/* The TLVs come after the image. */
/* After image there are TLVs. */
off = hdr->ih_img_size + hdr->ih_hdr_size;
rc = flash_area_read(fap, off, &info, sizeof(info));
if (rc) {
return rc;
}
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
return -1;
}
end = off + info.it_tlv_tot;
off += sizeof(info);
/*
* Traverse through all of the TLVs, performing any checks we know
* and are able to do.
*/
for (; off < end; off += sizeof(tlv) + tlv.it_len) {
rc = flash_area_read(fap, off, &tlv, sizeof tlv);
if (rc) {
return rc;
}
if (tlv.it_type == IMAGE_TLV_SHA256) {
/*
* Verify the SHA256 image hash. This must always be
* present.
*/
if (tlv.it_len != sizeof(hash)) {
return -1;
}
rc = flash_area_read(fap, off + sizeof(tlv), buf, sizeof hash);
if (rc) {
return rc;
}
if (memcmp(hash, buf, sizeof(hash))) {
return -1;
}
sha256_valid = 1;
#ifdef EXPECTED_SIG_TLV
} else if (tlv.it_type == IMAGE_TLV_KEYHASH) {
/*
* Determine which key we should be checking.
*/
if (tlv.it_len > 32) {
return -1;
}
rc = flash_area_read(fap, off + sizeof tlv, buf, tlv.it_len);
if (rc) {
return rc;
}
key_id = bootutil_find_key(buf, tlv.it_len);
/*
* The key may not be found, which is acceptable. There
* can be multiple signatures, each preceded by a key.
*/
} else if (tlv.it_type == EXPECTED_SIG_TLV) {
/* Ignore this signature if it is out of bounds. */
if (key_id < 0 || key_id >= bootutil_key_cnt) {
key_id = -1;
continue;
}
if (!EXPECTED_SIG_LEN(tlv.it_len) || tlv.it_len > sizeof(buf)) {
return -1;
}
rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
if (rc) {
return -1;
}
rc = bootutil_verify_sig(hash, sizeof(hash), buf, tlv.it_len, key_id);
if (rc == 0) {
valid_signature = 1;
}
key_id = -1;
#endif
}
}
if (!sha256_valid) {
return -1;
}
#ifdef EXPECTED_SIG_TLV
if (!valid_signature) {
return -1;
}
#endif
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -24,9 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <bootutil.h>
#include <bootutil/sign_key.h>
#include <bootutil/image.h>
#include <loader.h>
#include <wolfssl/ssl.h>
#if defined BOOT_SIGN_RSA

View File

@ -1,56 +0,0 @@
/* keys.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 <bootutil/sign_key.h>
#if defined(BOOT_SIGN_RSA)
#define HAVE_KEYS
extern const unsigned char rsa_pub_key[];
extern unsigned int rsa_pub_key_len;
#elif defined(BOOT_SIGN_EC256)
#define HAVE_KEYS
extern const unsigned char ecdsa_pub_key[];
extern unsigned int ecdsa_pub_key_len;
#elif defined(BOOT_SIGN_ED25519)
#define HAVE_KEYS
extern const unsigned char ed25519_pub_key[];
extern unsigned int ed25519_pub_key_len;
#else
#error "No public key available for given signing algorithm."
#endif
#if defined(HAVE_KEYS)
const struct bootutil_key bootutil_keys[] = {
{
#if defined(BOOT_SIGN_RSA)
.key = rsa_pub_key,
.len = &rsa_pub_key_len,
#elif defined(BOOT_SIGN_EC256)
.key = ecdsa_pub_key,
.len = &ecdsa_pub_key_len,
#elif defined(BOOT_SIGN_ED25519)
.key = ed25519_pub_key,
.len = &ed25519_pub_key_len,
#endif
},
};
const int bootutil_key_cnt = 1;
#endif

View File

@ -1,61 +0,0 @@
/* main.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 "target.h"
#include "hal.h"
#include "printf.h"
#include "bootutil/image.h"
#include "bootutil.h"
extern void do_boot(void *);
void main(void)
{
struct boot_rsp rsp;
int rc;
hal_init();
#ifdef TEST_PENDING
boot_set_pending(1);
#endif
wolfBoot_printf("Starting bootloader");
rc = boot_go(&rsp);
if (rc != 0) {
wolfBoot_printf("Unable to find bootable image");
while (1)
;
}
wolfBoot_printf("Bootloader chainload address offset: 0x%x",
rsp.br_image_off);
hal_prepare_boot();
wolfBoot_printf("Jumping to the first image slot");
do_boot((uint8_t *)0 + rsp.br_hdr->ih_load_addr);
wolfBoot_printf("something went wrong.");
while (1)
;
}

View File

@ -18,8 +18,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include "bootutil/image.h"
#include "bootutil.h"
#include <loader.h>
#include <stdint.h>
extern unsigned int _stored_data;
extern unsigned int _start_data;