From 0cb0e609b9a85d9c704ce213e5327c866d6eb5e0 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 30 Nov 2016 15:42:10 +0100 Subject: [PATCH 1/6] dist/tools: Add firmware metadata generator --- dist/tools/firmware_metadata/Makefile | 19 +++ dist/tools/firmware_metadata/README.md | 36 +++++ .../firmware_metadata/generate-metadata.c | 153 ++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 dist/tools/firmware_metadata/Makefile create mode 100644 dist/tools/firmware_metadata/README.md create mode 100644 dist/tools/firmware_metadata/generate-metadata.c diff --git a/dist/tools/firmware_metadata/Makefile b/dist/tools/firmware_metadata/Makefile new file mode 100644 index 000000000000..8c54f4c9530f --- /dev/null +++ b/dist/tools/firmware_metadata/Makefile @@ -0,0 +1,19 @@ +RIOTBASE := ../../.. +RIOT_INCLUDE = $(RIOTBASE)/sys/include +SHA256_DIR := $(RIOTBASE)/sys/hashes +SHA256_INCLUDE := $(RIOT_INCLUDE)/hashes +METADATA_SRC := generate-metadata.c $(SHA256_DIR)/sha256.c +METADATA_HDR := $(RIOT_INCLUDE)/hashes/sha256.h + +CFLAGS += -g -O3 -Wall -Wextra -pedantic -std=c99 + +all: bin/generate-metadata + +bin/: + mkdir -p bin + +bin/generate-metadata: $(METADATA_HDR) $(METADATA_SRC) | bin/ + $(CC) $(CFLAGS) -I$(RIOT_INCLUDE) $(METADATA_SRC) -o $@ + +clean: + rm -rf bin/generate-metadata diff --git a/dist/tools/firmware_metadata/README.md b/dist/tools/firmware_metadata/README.md new file mode 100644 index 000000000000..4ab7e3f1c35b --- /dev/null +++ b/dist/tools/firmware_metadata/README.md @@ -0,0 +1,36 @@ +# Metadata generator for firmware verification +This program generates a binary file containing a metadata structure as +follows: + +```c +typedef struct firmware_metadata { + uint8_t hash[SHA256_DIGEST_LENGTH]; /**< SHA256 Hash of firmware image */ + uint8_t shash[SIGN_LEN]; /**< Signed SHA256 */ + uint16_t version; /**< Integer representing firmware version */ + uint32_t size; /**< Size of firmware image */ + uint32_t appid; /**< Integer representing the application ID */ +} firmware_metadata_t; +``` + +This structure is filled with the data obtained from the firmware. + +## Usage +To use, you should call `generate-metadata` with the following arguments: + +```console +./generate-metadata +``` + +Where: + +_\\:_ The firmware in binary format + +_\\:_ The firmware version in 16-bit HEX + +_\_\: ID for the application in 32-bit HEX + +_\_\: The path for fimrware_metadata.bin + +If the operation succeeds, the results are printed out and a binary called +"firmware-metadata.bin" is written, if no _output-path_ option is specified, +in which case the file is written to the given path with the given name. diff --git a/dist/tools/firmware_metadata/generate-metadata.c b/dist/tools/firmware_metadata/generate-metadata.c new file mode 100644 index 000000000000..7597c9ec453d --- /dev/null +++ b/dist/tools/firmware_metadata/generate-metadata.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2016, Mark Solters . + * 2016, Inria + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * @ingroup FW + * @file + * @brief Meta-data generation for FW images + * + * @author Mark Solters + * @author Francisco Acosta + */ + +#include +#include +#include +#include + +#include "hashes/sha256.h" + +#define FW_METADATA_BIN "firmware-metadata.bin" + +typedef struct firmware_metadata { + uint8_t hash[SHA256_DIGEST_LENGTH]; /**< SHA256 Hash of firmware image */ + uint8_t shash[SHA256_DIGEST_LENGTH]; /**< Signed SHA256 */ + uint16_t version; /**< Integer representing firmware version */ + uint32_t size; /**< Size of firmware image */ + uint32_t appid; /**< Integer representing the application ID */ +} firmware_metadata_t; + +/* Input firmware .bin file */ +FILE *firmware_bin; + +/* Output metadata .bin file */ +FILE *metadata_bin; + +uint32_t firmware_size = 0; + +int main(int argc, char *argv[]) +{ + firmware_metadata_t metadata; + sha256_context_t firmware_sha256; + uint8_t output_buffer[sizeof(firmware_metadata_t)]; + int bytes_read = 0; + uint8_t firmware_buffer[1024]; + char firmware_metadata_path[128]; + + if (argc < 4) { + puts("Usage: generate-metadata [output path]"); + return -1; + } + + if (argv[4]) { + strcpy(firmware_metadata_path, argv[4]); + } + else { + strcpy(firmware_metadata_path, "firmware-metadata.bin"); + } + + /* Open the firmware .bin file */ + if (!(firmware_bin = fopen(argv[1], "r"))) { + printf("Error: No binary file found!\n"); + return -1; + } + + sha256_init(&firmware_sha256); + + while((bytes_read = fread(firmware_buffer, 1, sizeof(firmware_buffer), firmware_bin))) { + sha256_update(&firmware_sha256, firmware_buffer, bytes_read); + firmware_size += bytes_read; + } + sha256_final(&firmware_sha256, metadata.hash); + + printf("Firmware bytes read: %u\n", firmware_size); + + /* Close the .bin file. */ + fclose(firmware_bin); + + /* + * Fill with 0 the signed hash, as it's not yet implemented + */ + for (unsigned long i = 0; i < sizeof(metadata.shash); i++) { + metadata.shash[i] = 0; + } + + /* Generate FW image metadata */ + metadata.size = firmware_size; + sscanf(argv[2], "%xu", (unsigned int *)&(metadata.version)); + sscanf(argv[3], "%xu", &(metadata.appid)); + memcpy(output_buffer, (uint8_t*)&metadata, sizeof(firmware_metadata_t)); + + printf("Firmware Size: %d\n", metadata.size); + printf("Firmware Version: %#x\n", metadata.version); + printf("Firmware APPID: %#x\n", metadata.appid); + printf("Firmware HASH: "); + for (unsigned long i = 0; i < sizeof(metadata.hash); i++) { + printf("%02x ", metadata.hash[i]); + } + printf("\n"); + printf("Firmware signed HASH: "); + for (unsigned long i = 0; i < sizeof(metadata.shash); i++) { + printf("%02x ", metadata.shash[i]); + } + printf("\n"); + + /* Open the output firmware .bin file */ + metadata_bin = fopen(firmware_metadata_path, "w"); + + /* Write the metadata */ + printf("Metadata size: %lu\n", sizeof(firmware_metadata_t)); + fwrite(output_buffer, sizeof(output_buffer), 1, metadata_bin); + + /* 0xff spacing until firmware binary starts */ + uint8_t blank_buffer[256 - sizeof(firmware_metadata_t)]; + + for (unsigned long b = 0; b < sizeof(blank_buffer); b++) { + blank_buffer[b] = 0xff; + } + + fwrite(blank_buffer, sizeof(blank_buffer), 1, metadata_bin); + + /* Close the metadata file */ + fclose(metadata_bin); + + return 0; +} From 500d0d9db97c891a7b7ac31ba7a93b0b190c9cd9 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 24 Oct 2016 15:47:15 +0200 Subject: [PATCH 2/6] Makefile.include: add firmware-metadata target --- Makefile.include | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Makefile.include b/Makefile.include index 902a30950aba..d6226c8badfc 100644 --- a/Makefile.include +++ b/Makefile.include @@ -12,6 +12,7 @@ RIOTMAKE ?= $(RIOTBASE)/makefiles RIOTPKG ?= $(RIOTBASE)/pkg RIOTPROJECT ?= $(shell git rev-parse --show-toplevel 2>/dev/null || pwd) GITCACHE ?= $(RIOTBASE)/dist/tools/git/git-cache +FW_METADATA ?= $(RIOTBASE)/dist/tools/firmware_metadata APPDIR ?= $(CURDIR) BINDIRBASE ?= $(APPDIR)/bin BINDIR ?= $(BINDIRBASE)/$(BOARD) @@ -41,6 +42,7 @@ override RIOTMAKE := $(abspath $(RIOTMAKE)) override RIOTPKG := $(abspath $(RIOTPKG)) override RIOTPROJECT := $(abspath $(RIOTPROJECT)) override GITCACHE := $(abspath $(GITCACHE)) +override FW_METADATA := $(abspath $(FW_METADATA)) override APPDIR := $(abspath $(APPDIR)) override BINDIRBASE := $(abspath $(BINDIRBASE)) override BINDIR := $(abspath $(BINDIR)) @@ -280,6 +282,7 @@ BASELIBS += $(APPDEPS) ELFFILE ?= $(BINDIR)/$(APPLICATION).elf HEXFILE ?= $(ELFFILE:.elf=.hex) +BINFILE ?= $(ELFFILE:.elf=.bin) # variables used to compile and link c++ CPPMIX ?= $(if $(wildcard *.cpp),1,) @@ -303,9 +306,18 @@ else endif $(Q)$(SIZE) $(ELFFILE) $(Q)$(OBJCOPY) $(OFLAGS) $(ELFFILE) $(HEXFILE) + $(Q)$(OBJCOPY) -O binary $(ELFFILE) $(BINFILE) endif endif # BUILD_IN_DOCKER +firmware-metadata: all generate-metadata + $(Q)$(FW_METADATA)/bin/generate-metadata $(BINFILE) $(VERSION) $(APPID) $(BINDIR)/firmware-metadata.bin + +generate-metadata: $(FW_METADATA)/bin/generate-metadata + +$(FW_METADATA)/bin/generate-metadata: + $(Q)env -i make -C $(FW_METADATA) + ..compiler-check: @command -v $(CC) >/dev/null 2>&1 || \ { $(COLOR_ECHO) \ From 9f385e454daf0ca7ce5deb2252bb5f9f32943568 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 22 May 2017 15:31:45 +0200 Subject: [PATCH 3/6] f dist/tools: Add firmware metadata generator --- dist/tools/firmware_metadata/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dist/tools/firmware_metadata/README.md b/dist/tools/firmware_metadata/README.md index 4ab7e3f1c35b..074015b64fd6 100644 --- a/dist/tools/firmware_metadata/README.md +++ b/dist/tools/firmware_metadata/README.md @@ -25,12 +25,12 @@ Where: _\\:_ The firmware in binary format -_\\:_ The firmware version in 16-bit HEX +_\\:_ The firmware version in 16-bit HEX format -_\_\: ID for the application in 32-bit HEX +_\_\: ID for the application in 32-bit HEX format -_\_\: The path for fimrware_metadata.bin +_\_\: The path and name of the metadata binary file If the operation succeeds, the results are printed out and a binary called -"firmware-metadata.bin" is written, if no _output-path_ option is specified, -in which case the file is written to the given path with the given name. +"firmware-metadata.bin" is written, if no _output-path_ option is specified. +Otherwise, the file is written to the given path with the given name. From e908bd60608240956b51b03382ebcef420127768 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 22 May 2017 18:39:49 +0200 Subject: [PATCH 4/6] f Makefile.include: use BINFILE only inside metadata rule --- Makefile.include | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.include b/Makefile.include index d6226c8badfc..3b2ffed7665d 100644 --- a/Makefile.include +++ b/Makefile.include @@ -282,7 +282,6 @@ BASELIBS += $(APPDEPS) ELFFILE ?= $(BINDIR)/$(APPLICATION).elf HEXFILE ?= $(ELFFILE:.elf=.hex) -BINFILE ?= $(ELFFILE:.elf=.bin) # variables used to compile and link c++ CPPMIX ?= $(if $(wildcard *.cpp),1,) @@ -306,11 +305,12 @@ else endif $(Q)$(SIZE) $(ELFFILE) $(Q)$(OBJCOPY) $(OFLAGS) $(ELFFILE) $(HEXFILE) - $(Q)$(OBJCOPY) -O binary $(ELFFILE) $(BINFILE) endif endif # BUILD_IN_DOCKER firmware-metadata: all generate-metadata + BINFILE ?= $(ELFFILE:.elf=.bin) + $(Q)$(OBJCOPY) -O binary $(ELFFILE) $(BINFILE) $(Q)$(FW_METADATA)/bin/generate-metadata $(BINFILE) $(VERSION) $(APPID) $(BINDIR)/firmware-metadata.bin generate-metadata: $(FW_METADATA)/bin/generate-metadata From 0221cc3b918089b37f49f0bac9eeeed035ab37df Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 22 May 2017 18:40:28 +0200 Subject: [PATCH 5/6] f dist/tools/firmware_metadata: add space after while --- dist/tools/firmware_metadata/generate-metadata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/tools/firmware_metadata/generate-metadata.c b/dist/tools/firmware_metadata/generate-metadata.c index 7597c9ec453d..455c851a12a6 100644 --- a/dist/tools/firmware_metadata/generate-metadata.c +++ b/dist/tools/firmware_metadata/generate-metadata.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) sha256_init(&firmware_sha256); - while((bytes_read = fread(firmware_buffer, 1, sizeof(firmware_buffer), firmware_bin))) { + while ((bytes_read = fread(firmware_buffer, 1, sizeof(firmware_buffer), firmware_bin))) { sha256_update(&firmware_sha256, firmware_buffer, bytes_read); firmware_size += bytes_read; } From b0571746de4e1f7e96fcb99ec1d8a3cec6d0e5ce Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 23 May 2017 12:09:42 +0200 Subject: [PATCH 6/6] f dist/tools/firmware_metadata: rephrase --- dist/tools/firmware_metadata/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/tools/firmware_metadata/README.md b/dist/tools/firmware_metadata/README.md index 074015b64fd6..a25f3aef05b4 100644 --- a/dist/tools/firmware_metadata/README.md +++ b/dist/tools/firmware_metadata/README.md @@ -15,7 +15,7 @@ typedef struct firmware_metadata { This structure is filled with the data obtained from the firmware. ## Usage -To use, you should call `generate-metadata` with the following arguments: +To use it, call `generate-metadata` with the following arguments: ```console ./generate-metadata