From 9db78939bf3b9a8d2e9156930db7b6b0a885636e Mon Sep 17 00:00:00 2001 From: Ken Takayama <82209758+kentakayama@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:44:05 +0900 Subject: [PATCH] Read binaries from file interface on runtime (#39) * update: read binaries from file interface on runtime * add: AES-KW + Fetch + Slot example * del: unused headers --- Makefile.process | 21 ++-- examples/suit_manifest_process_main.c | 103 ++++++++++-------- ossl.Dockerfile | 4 +- ossl3.Dockerfile | 4 +- psa.Dockerfile | 4 +- .../8d82573a-926d-4754-9353-32dc29997f74.ta | 1 + testfiles/Makefile | 15 --- testfiles/suit_manifest_expAFS.cbor | Bin 0 -> 235 bytes testfiles/suit_manifest_expAFS.md | 91 ++++++++++++++++ 9 files changed, 165 insertions(+), 78 deletions(-) create mode 100644 testfiles/8d82573a-926d-4754-9353-32dc29997f74.ta delete mode 100644 testfiles/Makefile create mode 100644 testfiles/suit_manifest_expAFS.cbor create mode 100644 testfiles/suit_manifest_expAFS.md diff --git a/Makefile.process b/Makefile.process index 3de9354..ddda950 100644 --- a/Makefile.process +++ b/Makefile.process @@ -12,7 +12,7 @@ LDWRAP = \ -Xlinker --wrap=suit_invoke_callback \ -Xlinker --wrap=suit_condition_callback -INC = $(CMD_INC) -I ./inc -I ./examples/inc -I ./testfiles +INC = $(CMD_INC) -I ./inc -I ./examples/inc TARGET = ./bin/suit_manifest_process SRCS = \ examples/suit_examples_common.c \ @@ -27,11 +27,6 @@ SRCS = \ src/suit_manifest_print.c \ examples/suit_manifest_process_main.c OBJS = $(addprefix ./obj/,$(patsubst %.c,%.o,$(SRCS))) -BINARIES = \ - testfiles/suit_manifest_expU.cbor.h \ - testfiles/config.json.h \ - testfiles/suit_manifest_expS0.cbor.h \ - testfiles/encrypted_image_aes.bin.h ifeq ($(MBEDTLS),1) # use MbedTLS @@ -43,7 +38,7 @@ else endif .PHONY: all -all: $(BINARIES) $(TARGET) +all: $(TARGET) include Makefile.common @@ -53,15 +48,17 @@ $(TARGET): $(OBJS) | ./bin ./obj/%.o: %.c | ./obj/src ./obj/examples $(CC) $(CFLAGS) $(INC) $(CMD_LINE) -o $@ -c $< -./testfiles/%.h: - $(MAKE) -C testfiles $< - define test-one - $(TARGET) ./testfiles/suit_manifest_exp$(1).cbor || exit 1 + $(TARGET) ./testfiles/suit_manifest_exp$(1).cbor \ + -u "http://example.com/dependent.suit" -f "./testfiles/suit_manifest_expS0.cbor" \ + -u "https://example.com/encrypted-firmware" -f "./testfiles/encrypted_image_aes.bin" \ + -u "https://example.org/8d82573a-926d-4754-9353-32dc29997f74.suit" -f "./testfiles/suit_manifest_expU.cbor" \ + -u "https://example.org/8d82573a-926d-4754-9353-32dc29997f74.ta" -f "./testfiles/8d82573a-926d-4754-9353-32dc29997f74.ta" \ + -u "https://example.org/config.json" -f "./testfiles/config.json" || exit 1 endef -TEST_NUM := 0 1 2A 2B 3 4 5 U I D AF AW EW ED S0 S2 S3 S4 U0 U1 +TEST_NUM := 0 1 2A 2B 3 4 5 U I D AF AFS AW EW ED S0 S2 S3 S4 U0 U1 .PHONY: test test: all $(foreach num,$(TEST_NUM),$(call test-one,$(num))) diff --git a/examples/suit_manifest_process_main.c b/examples/suit_manifest_process_main.c index cb00463..92cfd17 100644 --- a/examples/suit_manifest_process_main.c +++ b/examples/suit_manifest_process_main.c @@ -14,7 +14,7 @@ #include #include // pid_t #include // waitpid -#include // fork +#include // fork, getopt, optarg #include // AT_FDCWD #include "csuit/suit_manifest_process.h" #include "csuit/suit_manifest_print.h" @@ -27,32 +27,11 @@ #include "trust_anchor_a128_cose_key_secret.h" #include "device_es256_cose_key_private.h" -#include "suit_manifest_expU.cbor.h" -#include "config.json.h" -#include "suit_manifest_expS0.cbor.h" -#include "encrypted_image_aes.bin.h" - -const uint8_t tc_uri[] = "https://example.org/8d82573a-926d-4754-9353-32dc29997f74.ta"; -const uint8_t tc_data[] = "Hello, Secure World!"; -const uint8_t depend_uri[] = "https://example.org/8d82573a-926d-4754-9353-32dc29997f74.suit"; -const uint8_t config_uri[] = "https://example.org/config.json"; -const uint8_t dependency_uri[] = "http://example.com/dependent.suit"; -const uint8_t encrypted_firmware_uri[] = "https://example.com/encrypted-firmware"; - -struct name_data { - const uint8_t *name; - size_t name_len; - const uint8_t *data; - size_t data_len; -}; -#define SUIT_NAME_DATA_LEN 5 -const struct name_data name_data[] = { - {.name = tc_uri, .name_len = sizeof(tc_uri) - 1, .data = tc_data, .data_len = sizeof(tc_data) - 1}, - {.name = depend_uri, .name_len = sizeof(depend_uri) - 1, .data = suit_manifest_expU_cbor, .data_len = suit_manifest_expU_cbor_len}, - {.name = config_uri, .name_len = sizeof(config_uri) - 1, .data = config_json, .data_len = config_json_len}, - {.name = dependency_uri, .name_len = sizeof(dependency_uri) - 1, .data = suit_manifest_expS0_cbor, .data_len = suit_manifest_expS0_cbor_len}, - {.name = encrypted_firmware_uri, .name_len = sizeof(encrypted_firmware_uri) - 1, .data = encrypted_image_aes_bin, .data_len = encrypted_image_aes_bin_len}, -}; +typedef struct { + char *url; + char *filename; +} UrlFilenamePair; +UrlFilenamePair pairs[SUIT_MAX_ARRAY_LENGTH] = {0}; suit_err_t __real_suit_fetch_callback(suit_fetch_args_t fetch_args, suit_fetch_ret_t *fetch_ret); suit_err_t __wrap_suit_fetch_callback(suit_fetch_args_t fetch_args, suit_fetch_ret_t *fetch_ret) @@ -69,22 +48,24 @@ suit_err_t __wrap_suit_fetch_callback(suit_fetch_args_t fetch_args, suit_fetch_r } size_t i = 0; - for (i = 0; i < SUIT_NAME_DATA_LEN; i++) { - if (name_data[i].name_len == fetch_args.uri_len - 1 && - memcmp(name_data[i].name, fetch_args.uri, name_data[i].name_len) == 0) { - if (fetch_args.buf_len < name_data[i].data_len) { + for (i = 0; i < SUIT_MAX_ARRAY_LENGTH; i++) { + if (pairs[i].url == NULL) { + continue; + } + if (memcmp(pairs[i].url, fetch_args.uri, fetch_args.uri_len) == 0) { + if (fetch_args.ptr == NULL) { return SUIT_ERR_NO_MEMORY; } - if (fetch_args.ptr != NULL) { - memcpy(fetch_args.ptr, name_data[i].data, name_data[i].data_len); - fetch_ret->buf_len = name_data[i].data_len; - } - write_to_file(filename, fetch_args.ptr, name_data[i].data_len); - printf("fetched %s\n\n", name_data[i].name); + FILE *f = fopen(pairs[i].filename, "r"); + fetch_ret->buf_len = fread(fetch_args.ptr, 1, fetch_args.buf_len, f); + fclose(f); + + write_to_file(filename, fetch_args.ptr, fetch_ret->buf_len); + printf("fetched from %s as %s (%ld bytes) to %s\n\n", pairs[i].filename, pairs[i].url, fetch_ret->buf_len, filename); break; } } - if (i == SUIT_NAME_DATA_LEN) { + if (i == SUIT_MAX_ARRAY_LENGTH) { /* not found */ /* ignore this for testing example 0-5 only */ //return SUIT_ERR_NOT_FOUND; @@ -376,13 +357,45 @@ suit_err_t __wrap_suit_store_callback(suit_store_args_t store_args) return result; } -int main(int argc, char *argv[]) +void display_help(const char *argv0, bool on_error) { - // check arguments. - if (argc < 2) { - printf("%s ", argv[0]); - return EXIT_FAILURE; + if (on_error) { + fprintf(stderr, "Usage: %s [-u -f ...]\n", argv0); + exit(EXIT_FAILURE); + } + printf("Usage: %s [-u -f ...]\n", argv0); + exit(EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) { + int opt; + int pair_count = 0; + + while ((opt = getopt(argc, argv, "u:f:h")) != -1) { + switch (opt) { + case 'u': + if (pair_count < SUIT_MAX_ARRAY_LENGTH) { + pairs[pair_count].url = optarg; + } + break; + case 'f': + if (pair_count < SUIT_MAX_ARRAY_LENGTH) { + if (pairs[pair_count].url == NULL) { + display_help(argv[0], true); + } + pairs[pair_count].filename = optarg; + pair_count++; + } + break; + case 'h': + display_help(argv[0], false); + break; + default: + display_help(argv[0], true); + break; + } } + suit_err_t result = 0; int num_key = 0; @@ -472,9 +485,9 @@ int main(int argc, char *argv[]) // Read manifest file. printf("\nmain : Read Manifest file.\n"); suit_inputs->manifest.ptr = suit_inputs->buf; - suit_inputs->manifest.len = read_from_file(argv[1], suit_inputs->buf, SUIT_MAX_DATA_SIZE); + suit_inputs->manifest.len = read_from_file(argv[optind], suit_inputs->buf, SUIT_MAX_DATA_SIZE); if (suit_inputs->manifest.len <= 0) { - printf("main : Failed to read Manifest file.\n"); + printf("main : Failed to read Manifest file. (%s)\n", argv[1]); return EXIT_FAILURE; } suit_inputs->left_len -= suit_inputs->manifest.len; diff --git a/ossl.Dockerfile b/ossl.Dockerfile index 5f5898c..071340c 100644 --- a/ossl.Dockerfile +++ b/ossl.Dockerfile @@ -27,5 +27,5 @@ RUN make -f Makefile.process CMD make test && \ make -f Makefile.encode test && \ make -f Makefile.parser test && \ - make -f Makefile.encrypt run && \ - make -f Makefile.process test + make -f Makefile.process test && \ + make -f Makefile.encrypt run diff --git a/ossl3.Dockerfile b/ossl3.Dockerfile index 35d91c6..4770d17 100644 --- a/ossl3.Dockerfile +++ b/ossl3.Dockerfile @@ -27,5 +27,5 @@ RUN make -f Makefile.process CMD make test && \ make -f Makefile.encode test && \ make -f Makefile.parser test && \ - make -f Makefile.encrypt run && \ - make -f Makefile.process test + make -f Makefile.process test && \ + make -f Makefile.encrypt run diff --git a/psa.Dockerfile b/psa.Dockerfile index 2ceb49c..209e966 100644 --- a/psa.Dockerfile +++ b/psa.Dockerfile @@ -31,5 +31,5 @@ RUN make -f Makefile.process MBEDTLS=1 CMD make test MBEDTLS=1 && \ make -f Makefile.encode MBEDTLS=1 test && \ make -f Makefile.parser MBEDTLS=1 test && \ - make -f Makefile.encrypt MBEDTLS=1 run && \ - make -f Makefile.process MBEDTLS=1 test + make -f Makefile.process MBEDTLS=1 test && \ + make -f Makefile.encrypt MBEDTLS=1 run diff --git a/testfiles/8d82573a-926d-4754-9353-32dc29997f74.ta b/testfiles/8d82573a-926d-4754-9353-32dc29997f74.ta new file mode 100644 index 0000000..7edbf53 --- /dev/null +++ b/testfiles/8d82573a-926d-4754-9353-32dc29997f74.ta @@ -0,0 +1 @@ +Hello, Secure World! \ No newline at end of file diff --git a/testfiles/Makefile b/testfiles/Makefile deleted file mode 100644 index c8467cf..0000000 --- a/testfiles/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (c) 2020-2024 SECOM CO., LTD. All Rights reserved. -# -# SPDX-License-Identifier: BSD-2-Clause -# - -.PHONY: all -all: suit_manifest_expU.cbor.h config.json.h suit_manifest_expS0.cbor.h encrypted_image_aes.bin.h - -%.h: % - xxd -i $< | sed -e 's/^unsigned char/const uint8_t/' -e 's/^unsigned int/const size_t/' > $@ - -.PHONY: clean -clean: - $(RM) *.h diff --git a/testfiles/suit_manifest_expAFS.cbor b/testfiles/suit_manifest_expAFS.cbor new file mode 100644 index 0000000000000000000000000000000000000000..2336e547542360d57eca3ff397d104ae23823a8d GIT binary patch literal 235 zcmVJQ-W9|f-hJgrqaPW4e!-@3HoKiLI$a*baG+l>H&2!v)ZshoI;}f zSSrzkL!ki$p!QfG+cgTwU^@%CIF-0i8EKPaKQT&>W@Ae+zhdQ<{f7iJ16Yrw0RaL5 z14*F*f`LH*fk6QjSbU5O0TiMR7%mlfCTMhYaC15@FJ*XPZE$R5E@N+PFJ*3Ha(Qrc zWn?X8X>x6MVRB^^4-5blq7zs?*kFW1p#cG*1x)cutDS+>A9~qC{)hH~gFvDIA_PTi lX=E)iSQvF+Km3&#*OYNQjHsa%r~5KiT5VZVO=1=S77w` + +## Example 1: Fetch and Decrypt AES-KW + Encrypted Payload +{: numbered='no'} + +### CBOR Diagnostic Notation of SUIT Manifest +{: numbered='no'} + +~~~~ +/ SUIT_Envelope_Tagged / 107({ + / authentication-wrapper / 2: << [ + << [ + / digest-algorithm-id: / -16 / SHA256 /, + / digest-bytes: / h'A6D2C13A0DEFD57A09FA65C24206A9A8747261E6EA017532B3DAB0419C42A2FC' + ] >>, + << / COSE_Mac0_Tagged / 17([ + / protected: / << { + / algorithm-id / 1: 5 / HMAC256 / + } >>, + / unprotected: / {}, + / payload: / null, + / tag: / h'DB350AC9603B0BBA3895B850196993633F314A9066634B31BF62E596FD870434' + ]) >> + ] >>, + / manifest / 3: << { + / manifest-version / 1: 1, + / manifest-sequence-number / 2: 1, + / common / 3: << { + / components / 2: [ + [h'00'], + [h'01'] + ] + } >>, + / install / 20: << [ + / fetch encrypted firmware / + / directive-set-component-index / 12, 1 / [h'01'] /, + / directive-override-parameters / 20, { + / parameter-image-size / 14: 46, + / parameter-uri / 21: "https://example.com/encrypted-firmware" + }, + / directive-fetch / 21, 15, + + / decrypt encrypted firmware / + / directive-set-component-index / 12, 0 / ['00'] /, + / directive-override-parameters / 20, { + / parameter-encryption-info / 19: << 96([ + / protected: / << { + / alg / 1: 1 / A128GCM / + } >>, + / unprotected: / { + / IV / 5: h'F14AAB9D81D51F7AD943FE87' + }, + / payload: / null / detached ciphertext /, + / recipients: / [ + [ + / protected: / h'', + / unprotected: / { + / alg / 1: -3 / A128KW /, + / kid / 4: 'kid-1' + }, + / payload: / h'75603FFC9518D794713C8CA8A115A7FB32565A6D59534D62' / CEK encrypted with KEK / + ] + ] + ]) >>, + / parameter-source-component / 22: 1 / [h'01'] / + }, + / directive-copy / 22, 15 + / consumes the SUIT_Encryption_Info above / + ] >> + } >> +}) +~~~~ + + +### CBOR Binary in Hex +{: numbered='no'} + +~~~~ +D86BA2025853825824822F5820A6D2C13A0DEFD57A09FA65C24206A9A874 +7261E6EA017532B3DAB0419C42A2FC582AD18443A10105A0F65820DB350A +C9603B0BBA3895B850196993633F314A9066634B31BF62E596FD87043403 +588FA4010102010349A1028281410081410114587C8C0C0114A20E182E15 +782668747470733A2F2F6578616D706C652E636F6D2F656E637279707465 +642D6669726D77617265150F0C0014A213583ED8608443A10101A1054CF1 +4AAB9D81D51F7AD943FE87F6818340A2012204456B69642D31581875603F +FC9518D794713C8CA8A115A7FB32565A6D59534D621601160F +~~~~