From a1c7d0dbdd595e66ea9fb2c8fb4baf94acf793c6 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 16 Aug 2023 15:07:53 -0700 Subject: [PATCH] Adding GitHub Action for testing TPM features. --- .github/workflows/footprint.yml | 4 +- .github/workflows/test-build-sim-tpm.yml | 63 +++++ .github/workflows/test-configs.yml | 4 +- .github/workflows/test-keytools.yml | 4 +- .../workflows/test-powerfail-simulator.yml | 4 +- .../test-renode-fastmath-smallstack.yml | 4 +- .github/workflows/test-renode-fastmath.yml | 4 +- .../test-renode-noasm-smallstack.yml | 4 +- .github/workflows/test-renode-noasm.yml | 4 +- .github/workflows/test-renode-nrf52.yml | 4 +- .github/workflows/test-renode-sha3.yml | 4 +- .github/workflows/test-renode-sha384.yml | 4 +- .github/workflows/test-renode-smallstack.yml | 4 +- .github/workflows/test-tpm.yml | 75 ++++++ .github/workflows/test-units.yml | 4 +- .gitignore | 1 + Makefile | 5 + config/examples/sim-tpm-keystore.config | 9 +- config/examples/sim-tpm-measured.config | 2 +- config/examples/sim-tpm.config | 4 +- hal/sim.c | 2 +- include/keystore.h | 62 +++++ include/wolfboot/wolfboot.h | 18 +- lib/wolfTPM | 2 +- src/image.c | 2 +- tools/keytools/keygen.c | 6 +- tools/keytools/keygen.py | 4 +- tools/keytools/user_settings.h | 26 +- tools/tpm/Makefile | 96 +++++++ tools/tpm/README.md | 15 ++ tools/tpm/rot.c | 255 ++++++++++++++++++ tools/tpm/user_settings.h | 97 +++++++ 32 files changed, 731 insertions(+), 65 deletions(-) create mode 100644 .github/workflows/test-build-sim-tpm.yml create mode 100644 .github/workflows/test-tpm.yml create mode 100644 include/keystore.h create mode 100644 tools/tpm/Makefile create mode 100644 tools/tpm/README.md create mode 100644 tools/tpm/rot.c create mode 100644 tools/tpm/user_settings.h diff --git a/.github/workflows/footprint.yml b/.github/workflows/footprint.yml index 5635193bf..cd5db3b7c 100644 --- a/.github/workflows/footprint.yml +++ b/.github/workflows/footprint.yml @@ -2,9 +2,9 @@ name: Footprint test on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: footprint_test: diff --git a/.github/workflows/test-build-sim-tpm.yml b/.github/workflows/test-build-sim-tpm.yml new file mode 100644 index 000000000..48814f451 --- /dev/null +++ b/.github/workflows/test-build-sim-tpm.yml @@ -0,0 +1,63 @@ +name: Wolfboot Reusable Build Workflow for TPM with Simulator + +on: + + workflow_call: + inputs: + arch: + required: true + type: string + config-file: + required: true + type: string + make-args: + required: false + type: string + rot-args: + required: false + type: string + +jobs: + + build: + runs-on: ubuntu-20.04 + + steps: + # setup ibmswtpm2 + - uses: actions/checkout@master + with: + repository: kgoldman/ibmswtpm2 + path: ibmswtpm2 + - name: ibmswtpm2 make + working-directory: ./ibmswtpm2/src + run: | + make + ./ibmswtpm2/src/tpm_server & + + - uses: actions/checkout@v3 + with: + submodules: true + + - name: make distclean + run: | + make distclean + + - name: Select config + run: | + cp ${{inputs.config-file}} .config + + - name: Build tools + run: | + make keytools && make tpmtools + + - name: Write TPM ROT to TPM + run: | + ./tools/tpm/rot -write ${{inputs.rot-args}} + + - name: Build wolfboot + run: | + make ${{inputs.make-args}} + + - name: Run wolfBoot + run: | + ./wolfboot.elf get_version diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 50589f552..ef38af4ad 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -2,9 +2,9 @@ name: Test Example Configs on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: diff --git a/.github/workflows/test-keytools.yml b/.github/workflows/test-keytools.yml index 2de7c9f24..4adff0613 100644 --- a/.github/workflows/test-keytools.yml +++ b/.github/workflows/test-keytools.yml @@ -2,9 +2,9 @@ name: Wolfboot keytools test workflow on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: diff --git a/.github/workflows/test-powerfail-simulator.yml b/.github/workflows/test-powerfail-simulator.yml index f1ff2377a..fb0262214 100644 --- a/.github/workflows/test-powerfail-simulator.yml +++ b/.github/workflows/test-powerfail-simulator.yml @@ -2,9 +2,9 @@ name: Power-failure during update - test with simulator target on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: powerfail_simulator_tests: diff --git a/.github/workflows/test-renode-fastmath-smallstack.yml b/.github/workflows/test-renode-fastmath-smallstack.yml index 881c0b6b9..2d5f68369 100644 --- a/.github/workflows/test-renode-fastmath-smallstack.yml +++ b/.github/workflows/test-renode-fastmath-smallstack.yml @@ -2,9 +2,9 @@ name: Renode Automated multi memory configurations on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: renode_automated_fastmath_smallstack: diff --git a/.github/workflows/test-renode-fastmath.yml b/.github/workflows/test-renode-fastmath.yml index 97f0f159f..6b31f07a9 100644 --- a/.github/workflows/test-renode-fastmath.yml +++ b/.github/workflows/test-renode-fastmath.yml @@ -2,9 +2,9 @@ name: Renode Automated multi memory configurations on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: renode_automated_fastmath: diff --git a/.github/workflows/test-renode-noasm-smallstack.yml b/.github/workflows/test-renode-noasm-smallstack.yml index e4fb0cd54..4e3a3fad2 100644 --- a/.github/workflows/test-renode-noasm-smallstack.yml +++ b/.github/workflows/test-renode-noasm-smallstack.yml @@ -2,9 +2,9 @@ name: Renode Automated multi memory configurations on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: renode_automated_noasm_smallstack: diff --git a/.github/workflows/test-renode-noasm.yml b/.github/workflows/test-renode-noasm.yml index 218230f4b..0b072a539 100644 --- a/.github/workflows/test-renode-noasm.yml +++ b/.github/workflows/test-renode-noasm.yml @@ -2,9 +2,9 @@ name: Renode Automated multi memory configurations on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: renode_automated_noasm: diff --git a/.github/workflows/test-renode-nrf52.yml b/.github/workflows/test-renode-nrf52.yml index e12316c79..833548181 100644 --- a/.github/workflows/test-renode-nrf52.yml +++ b/.github/workflows/test-renode-nrf52.yml @@ -2,9 +2,9 @@ name: Renode Automated - Base Tests on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: renode_automated_base: diff --git a/.github/workflows/test-renode-sha3.yml b/.github/workflows/test-renode-sha3.yml index 681ff0863..05292874c 100644 --- a/.github/workflows/test-renode-sha3.yml +++ b/.github/workflows/test-renode-sha3.yml @@ -2,9 +2,9 @@ name: Renode Automated multi SHA algorithms on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: renode_automated_multi_sha: diff --git a/.github/workflows/test-renode-sha384.yml b/.github/workflows/test-renode-sha384.yml index 51a28b3a2..2d7cde579 100644 --- a/.github/workflows/test-renode-sha384.yml +++ b/.github/workflows/test-renode-sha384.yml @@ -2,9 +2,9 @@ name: Renode Automated multi SHA algorithms on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: renode_automated_multi_sha: diff --git a/.github/workflows/test-renode-smallstack.yml b/.github/workflows/test-renode-smallstack.yml index 513f3a096..11ad29c6a 100644 --- a/.github/workflows/test-renode-smallstack.yml +++ b/.github/workflows/test-renode-smallstack.yml @@ -2,9 +2,9 @@ name: Renode Automated multi memory configurations on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: renode_automated_smallstack: diff --git a/.github/workflows/test-tpm.yml b/.github/workflows/test-tpm.yml new file mode 100644 index 000000000..63edc0ac4 --- /dev/null +++ b/.github/workflows/test-tpm.yml @@ -0,0 +1,75 @@ +name: Test TPM Configs + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +jobs: + + sim_tpm_ecc256: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm.config + make-args: SIGN=ECC256 HASH=SHA256 + + sim_tpm_ecc384: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm.config + make-args: SIGN=ECC384 HASH=SHA384 + + sim_tpm_rsa2048: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm.config + make-args: SIGN=RSA2048 HASH=SHA256 + + + sim_tpm_measure_ecc256: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-measured.config + make-args: SIGN=ECC256 HASH=SHA256 + + sim_tpm_measure_ecc384: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-measured.config + make-args: SIGN=ECC384 HASH=SHA384 + + sim_tpm_measure_rsa2048: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-measured.config + make-args: SIGN=RSA2048 HASH=SHA256 + + + sim_tpm_keystore_ecc256: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-keystore.config + make-args: SIGN=ECC256 HASH=SHA256 + + sim_tpm_keystore_ecc384: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-keystore.config + make-args: SIGN=ECC384 HASH=SHA384 + rot-args: -sha384 + + sim_tpm_keystore_rsa2048: + uses: ./.github/workflows/test-build-sim-tpm.yml + with: + arch: host + config-file: ./config/examples/sim-tpm-keystore.config + make-args: SIGN=RSA2048 HASH=SHA256 diff --git a/.github/workflows/test-units.yml b/.github/workflows/test-units.yml index e95a722ef..25fc97d36 100644 --- a/.github/workflows/test-units.yml +++ b/.github/workflows/test-units.yml @@ -2,9 +2,9 @@ name: Unit tests on: push: - branches: [master] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [master] + branches: [ '*' ] jobs: unit_tests: diff --git a/.gitignore b/.gitignore index f686728c1..c94c5b381 100644 --- a/.gitignore +++ b/.gitignore @@ -100,6 +100,7 @@ tools/uart-flash-server/ufserver tools/unit-tests/unit-parser tools/bin-assemble/bin-assemble tools/elf-parser/elf-parser +tools/tpm/rot config/*.ld # Generated confiuguration file diff --git a/Makefile b/Makefile index f99afb7ea..f00503d24 100644 --- a/Makefile +++ b/Makefile @@ -167,6 +167,11 @@ keytools: @$(MAKE) -C tools/keytools -s clean @$(MAKE) -C tools/keytools -j +tpmtools: + @echo "Building TPM tools" + @$(MAKE) -C tools/tpm -s clean + @$(MAKE) -C tools/tpm -j + test-app/image_v1_signed.bin: $(BOOT_IMG) @echo "\t[SIGN] $(BOOT_IMG)" $(Q)(test $(SIGN) = NONE) || $(SIGN_TOOL) $(SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) 1 diff --git a/config/examples/sim-tpm-keystore.config b/config/examples/sim-tpm-keystore.config index 27852fbb0..4d81a0afe 100644 --- a/config/examples/sim-tpm-keystore.config +++ b/config/examples/sim-tpm-keystore.config @@ -1,11 +1,16 @@ ARCH=sim TARGET=sim -SIGN?=ECC384 -HASH?=SHA384 +SIGN?=ECC256 +HASH?=SHA256 SPI_FLASH=0 DEBUG=1 WOLFTPM=1 +# Measured boot at test PCR index 16 +MEASURED_BOOT?=1 +MEASURED_PCR_A?=16 + +# Use NV for TPM based Root of Trust WOLFBOOT_TPM_KEYSTORE?=1 WOLFBOOT_TPM_KEYSTORE_NV_INDEX?=0x01400200 diff --git a/config/examples/sim-tpm-measured.config b/config/examples/sim-tpm-measured.config index cd1f57bb1..bba9d5a8a 100644 --- a/config/examples/sim-tpm-measured.config +++ b/config/examples/sim-tpm-measured.config @@ -1,6 +1,6 @@ ARCH=sim TARGET=sim -SIGN?=ED25519 +SIGN?=ECC256 HASH?=SHA256 WOLFBOOT_SMALL_STACK=1 SPI_FLASH=0 diff --git a/config/examples/sim-tpm.config b/config/examples/sim-tpm.config index 0065ae61d..e34d90426 100644 --- a/config/examples/sim-tpm.config +++ b/config/examples/sim-tpm.config @@ -1,7 +1,7 @@ ARCH=sim TARGET=sim -SIGN?=ECC384 -HASH?=SHA384 +SIGN?=ECC256 +HASH?=SHA256 SPI_FLASH=0 DEBUG=1 WOLFTPM=1 diff --git a/hal/sim.c b/hal/sim.c index 66f05a204..71cd34950 100644 --- a/hal/sim.c +++ b/hal/sim.c @@ -140,7 +140,7 @@ void hal_init(void) ret = mmap_file(EXTERNAL_FLASH_FILE, (uint8_t*)ARCH_FLASH_OFFSET + 0x10000000, &flash_base); if (ret != 0) { - fprintf(stderr, "failed to load internal flash file\n"); + fprintf(stderr, "failed to load external flash file\n"); exit(-1); } #endif /* EXT_FLASH */ diff --git a/include/keystore.h b/include/keystore.h new file mode 100644 index 000000000..d2929832a --- /dev/null +++ b/include/keystore.h @@ -0,0 +1,62 @@ +/* keystore.h + * + * API's for key store + * + * + * Copyright (C) 2023 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 KEYSTORE_H +#define KEYSTORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef KEYSTORE_PUBKEY_SIZE + /* allow building version for external API use */ + #define KEYSTORE_ANY + #define KEYSTORE_PUBKEY_SIZE 576 /* Max is RSA 4096 */ +#endif + +struct keystore_slot { + uint32_t slot_id; + uint32_t key_type; + uint32_t part_id_mask; + uint32_t pubkey_size; + uint8_t pubkey[KEYSTORE_PUBKEY_SIZE]; +}; + +/* KeyStore API */ +int keystore_num_pubkeys(void); +#if defined(WOLFBOOT_RENESAS_SCEPROTECT) + uint32_t *keystore_get_buffer(int id); +#else + uint8_t *keystore_get_buffer(int id); +#endif +int keystore_get_size(int id); +uint32_t keystore_get_key_type(int id); +uint32_t keystore_get_mask(int id); + + +#ifdef __cplusplus +} +#endif + +#endif /* KEYSTORE_H */ diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index 499b788c4..d4bd64a94 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -199,23 +199,7 @@ extern "C" { "Please select a valid SIGN= option." #endif /* authentication options */ - struct keystore_slot { - uint32_t slot_id; - uint32_t key_type; - uint32_t part_id_mask; - uint32_t pubkey_size; - uint8_t pubkey[KEYSTORE_PUBKEY_SIZE]; - }; - - /* KeyStore API */ - int keystore_num_pubkeys(void); -#if defined(WOLFBOOT_RENESAS_SCEPROTECT) - uint32_t *keystore_get_buffer(int id); -#else - uint8_t *keystore_get_buffer(int id); -#endif - int keystore_get_size(int id); - uint32_t keystore_get_mask(int id); + #include "keystore.h" #endif /* defined WOLFBOOT */ diff --git a/lib/wolfTPM b/lib/wolfTPM index b159d7047..2d0ae5f2a 160000 --- a/lib/wolfTPM +++ b/lib/wolfTPM @@ -1 +1 @@ -Subproject commit b159d7047a71072b158c1f1738d3f7047bca9402 +Subproject commit 2d0ae5f2a8419154d02f00efc9b9dc24978123bf diff --git a/src/image.c b/src/image.c index 1e0bebba4..cff7e67d1 100644 --- a/src/image.c +++ b/src/image.c @@ -712,7 +712,7 @@ static void wolfBoot_PrintBin(const byte* buffer, word32 length) word32 i, sz; if (!buffer) { - wolfBoot_printf("\tNULL"); + wolfBoot_printf("\tNULL\n"); return; } diff --git a/tools/keytools/keygen.c b/tools/keytools/keygen.c index 425422ea4..72cd31602 100644 --- a/tools/keytools/keygen.c +++ b/tools/keytools/keygen.c @@ -104,13 +104,13 @@ const char Cfile_Banner[]="/* Keystore file for wolfBoot, automatically generate "/*\n" " * This file has been generated and contains the public keys\n" " * used by wolfBoot to verify the updates.\n" - " */" \ - "\n#include \n#include \"wolfboot/wolfboot.h\"\n" + " */" + "\n#include \n#include \"wolfboot/wolfboot.h\"\n#include \"keystore.h\"\n" #if defined(WOLFBOOT_RENESAS_TSIP) "#include \"key_data.h\"\n" #endif "#ifdef WOLFBOOT_NO_SIGN\n\t#define NUM_PUBKEYS 0\n#else\n\n" - "#if (KEYSTORE_PUBKEY_SIZE != KEYSTORE_PUBKEY_SIZE_%s)\n\t" + "#if !defined(KEYSTORE_ANY) && (KEYSTORE_PUBKEY_SIZE != KEYSTORE_PUBKEY_SIZE_%s)\n\t" "#error Key algorithm mismatch. Remove old keys via 'make keysclean'\n" "#else\n"; diff --git a/tools/keytools/keygen.py b/tools/keytools/keygen.py index dc88f261b..5544e6cc4 100755 --- a/tools/keytools/keygen.py +++ b/tools/keytools/keygen.py @@ -136,9 +136,9 @@ def keystore_add(slot, pub, sz = 0): " * This file has been generated and contains the public keys\n"+ \ " * used by wolfBoot to verify the updates.\n"+ \ " */" \ - "\n#include \n#include \"wolfboot/wolfboot.h\"\n" \ + "\n#include \n#include \"wolfboot/wolfboot.h\"\n#include \"keystore.h\"\n" \ "#ifdef WOLFBOOT_NO_SIGN\n\t#define NUM_PUBKEYS 0\n#else\n\n" \ - "#if (KEYSTORE_PUBKEY_SIZE != KEYSTORE_PUBKEY_SIZE_%s)\n\t" \ + "#if !defined(KEYSTORE_ANY) && (KEYSTORE_PUBKEY_SIZE != KEYSTORE_PUBKEY_SIZE_%s)\n\t" \ "#error Key algorithm mismatch. Remove old keys via 'make keysclean'\n" \ "#else\n" diff --git a/tools/keytools/user_settings.h b/tools/keytools/user_settings.h index 23e814cd4..1981dc2c5 100644 --- a/tools/keytools/user_settings.h +++ b/tools/keytools/user_settings.h @@ -29,22 +29,29 @@ #include /* System */ -#define WOLFSSL_GENERAL_ALIGNMENT 4 #define SINGLE_THREADED #define WOLFCRYPT_ONLY -#define SIZEOF_LONG_LONG 8 /* Math */ -#define WOLFSSL_SP -#define USE_FAST_MATH -#define FP_MAX_BITS (4096 * 2) +#if 1 + #define USE_FAST_MATH + #define FP_MAX_BITS (4096 * 2) +#else + #define WOLFSSL_SP_MATH + #define WOLFSSL_HAVE_SP_ECC + #define WOLFSSL_SP_384 + #define WOLFSSL_SP_521 + #define WOLFSSL_HAVE_SP_RSA + #define WOLFSSL_SP_4096 +#endif + #define TFM_TIMING_RESISTANT /* ECC */ #define HAVE_ECC -#define WOLFSSL_HAVE_SP_ECC #define ECC_TIMING_RESISTANT -#define HAVE_ECC256 +#define ECC_USER_CURVES +#undef NO_ECC256 #define HAVE_ECC384 #define HAVE_ECC521 @@ -57,7 +64,6 @@ /* RSA */ #define HAVE_RSA -#define WOLFSSL_HAVE_SP_RSA #define WC_RSA_BLINDING #define WOLFSSL_KEY_GEN @@ -67,6 +73,9 @@ #define WOLFSSL_SHA3 #undef NO_SHA256 +/* ASN */ +#define WOLFSSL_ASN_TEMPLATE + /* Chacha stream cipher */ #define HAVE_CHACHA @@ -97,7 +106,6 @@ #define NO_WOLFSSL_DIR #define WOLFSSL_NO_SOCK #define WOLFSSL_IGNORE_FILE_WARN -#define NO_ERROR_STRINGS #define BENCH_EMBEDDED #define NO_CRYPT_TEST diff --git a/tools/tpm/Makefile b/tools/tpm/Makefile new file mode 100644 index 000000000..c150d64a2 --- /dev/null +++ b/tools/tpm/Makefile @@ -0,0 +1,96 @@ +# wolfBoot TPM Tools + +-include ../../.config + +V?=0 +ifeq ($(V),0) + Q=@ +endif + +CC = gcc +LD = gcc +WOLFBOOTDIR = ../.. +WOLFDIR = $(WOLFBOOTDIR)/lib/wolfssl/ +WOLFTPMDIR = $(WOLFBOOTDIR)/lib/wolfTPM/ +CFLAGS = -Wall -Wextra -Werror +CFLAGS += -I. -DWOLFSSL_USER_SETTINGS -DWOLFTPM_USER_SETTINGS -I$(WOLFDIR) -I$(WOLFTPMDIR) -I$(WOLFBOOTDIR)/include +LDFLAGS = +OBJDIR = ./ + +# option variables +DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE -fsanitize=address +OPTIMIZE = -O2 + +# Options +#CFLAGS+=$(DEBUG_FLAGS) +CFLAGS+=$(OPTIMIZE) + +ifeq ($(TARGET),sim) + CFLAGS+=-D"WOLFTPM_SWTPM" +endif + +# Sources +OBJS_REAL=\ + $(WOLFBOOTDIR)/src/keystore.o \ + $(WOLFDIR)wolfcrypt/src/asn.o \ + $(WOLFDIR)wolfcrypt/src/aes.o \ + $(WOLFDIR)wolfcrypt/src/ecc.o \ + $(WOLFDIR)wolfcrypt/src/error.o \ + $(WOLFDIR)wolfcrypt/src/coding.o \ + $(WOLFDIR)wolfcrypt/src/hash.o \ + $(WOLFDIR)wolfcrypt/src/logging.o \ + $(WOLFDIR)wolfcrypt/src/memory.o \ + $(WOLFDIR)wolfcrypt/src/random.o \ + $(WOLFDIR)wolfcrypt/src/rsa.o \ + $(WOLFDIR)wolfcrypt/src/hmac.o \ + $(WOLFDIR)wolfcrypt/src/sp_int.o \ + $(WOLFDIR)wolfcrypt/src/sp_c32.o \ + $(WOLFDIR)wolfcrypt/src/sp_c64.o \ + $(WOLFDIR)wolfcrypt/src/sha256.o \ + $(WOLFDIR)wolfcrypt/src/sha512.o \ + $(WOLFDIR)wolfcrypt/src/tfm.o \ + $(WOLFDIR)wolfcrypt/src/wc_port.o \ + $(WOLFDIR)wolfcrypt/src/wolfmath.o \ + $(WOLFTPMDIR)src/tpm2_wrap.o \ + $(WOLFTPMDIR)src/tpm2.o \ + $(WOLFTPMDIR)src/tpm2_linux.o \ + $(WOLFTPMDIR)src/tpm2_packet.o \ + $(WOLFTPMDIR)src/tpm2_param_enc.o \ + $(WOLFTPMDIR)src/tpm2_swtpm.o \ + $(WOLFTPMDIR)src/tpm2_tis.o \ + $(WOLFTPMDIR)src/tpm2_winapi.o \ + $(WOLFTPMDIR)hal/tpm_io.o + +OBJS_VIRT=$(addprefix $(OBJDIR), $(notdir $(OBJS_REAL))) +vpath %.c $(WOLFDIR)/wolfcrypt/src/ +vpath %.c $(WOLFBOOTDIR)/src/ +vpath %.c $(WOLFTPMDIR)/src/ +vpath %.c $(WOLFTPMDIR)/hal/ +vpath %.c ./ + +.PHONY: clean all + +all: rot + +debug: CFLAGS+=$(DEBUG_FLAGS) +debug: all + +# build objects +$(OBJDIR)/%.o: %.c + $(Q)$(CC) $(CFLAGS) -c -o $@ $< +$(OBJDIR)/%.o: $(WOLFBOOTDIR)/src/%.c + $(Q)$(CC) $(CFLAGS) -c -o $@ $< +$(OBJDIR)/%.o: $(WOLFDIR)/wolfcrypt/src/%.c + $(Q)$(CC) $(CFLAGS) -c -o $@ $< +$(OBJDIR)/%.o: $(WOLFTPMDIR)/src/%.c + $(Q)$(CC) $(CFLAGS) -c -o $@ $< +$(OBJDIR)/%.o: $(WOLFTPMDIR)/hal/%.c + $(Q)$(CC) $(CFLAGS) -c -o $@ $< + +# build templates +rot: $(OBJS_VIRT) rot.o + @echo "Building Root of Trust (ROT) tool" + $(Q)$(LD) -o $@ $@.o $(OBJS_VIRT) $(LDFLAGS) + +clean: + rm -f rot *.o diff --git a/tools/tpm/README.md b/tools/tpm/README.md new file mode 100644 index 000000000..123ba7b57 --- /dev/null +++ b/tools/tpm/README.md @@ -0,0 +1,15 @@ +# TPM Tools for wolfBoot + +Tools to help with TPM setup. + +For wolfBoot TPM features see (docs/TPM.md)[/docs/TPM.md]. + +# Secure Boot Root of Trust (ROT) + +Examples: + +* `./tools/tpm/rot`: Parse keystore.c keys, hash each and read NV values. +* `./tools/tpm/rot -write`: Also write hash to NV. +* `./tools/tpm/rot -write -lock`: Write and lock the NV +* `./tools/tpm/rot -write -sha384`: Write NV using SHA2-384 +* `./tools/tpm/rot -write -auth=test`: Use password for NV access diff --git a/tools/tpm/rot.c b/tools/tpm/rot.c new file mode 100644 index 000000000..8a529eb0f --- /dev/null +++ b/tools/tpm/rot.c @@ -0,0 +1,255 @@ +/* rot.c + * + * Copyright (C) 2023 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 +#include + +#include +#include +#include +#include +#include + +#define TPM2_DEMO_NV_SECURE_ROT_INDEX 0x01400200 + +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./tools/tpm/rot [-nvindex] [-write] [-auth] [-sha384] [-lock]\n"); + printf("* -nvindex=[handle] (default 0x%x)\n", TPM2_DEMO_NV_SECURE_ROT_INDEX); + printf("* -write: Using keystore.c API's hashes each public key and stores into NV\n"); + printf("* -auth=password: Optional password for NV\n"); + printf("* -sha384: Use SHA2-384 (default is SHA2-256)\n"); + printf("* -lock: Lock the write\n"); + printf("\nExamples:\n"); + printf("\t./tools/tpm/rot\n"); + printf("\t./tools/tpm/rot -write\n"); +} + +int TPM2_Boot_SecureROT_Example(TPMI_RH_NV_AUTH authHandle, word32 nvIndex, + enum wc_HashType hashType, int doWrite, int doLock, + const char *authBuf, int authBufSz) +{ + int rc; + WOLFTPM2_DEV dev; + WOLFTPM2_SESSION tpmSession; + WOLFTPM2_HANDLE parent; + WOLFTPM2_NV nv; + TPMS_NV_PUBLIC nvPublic; + word32 nvAttributes; + /* always use AES CFB parameter encryption */ + int paramEncAlg = TPM_ALG_CFB; + byte digest[WC_MAX_DIGEST_SIZE]; + int digestSz = 0; + int id; + + XMEMSET(&tpmSession, 0, sizeof(tpmSession)); + XMEMSET(&parent, 0, sizeof(parent)); + XMEMSET(digest, 0, sizeof(digest)); + + /* setup the parent handle OWNER/PLATFORM */ + parent.hndl = authHandle; + + rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL); + if (rc != TPM_RC_SUCCESS) { + printf("\nwolfTPM2_Init failed\n"); + goto exit; + } + + /* Start TPM session for parameter encryption */ + printf("Parameter Encryption: Enabled %s and HMAC\n\n", + TPM2_GetAlgName(paramEncAlg)); + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_HMAC, paramEncAlg); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + /* Set TPM session attributes for parameter encryption */ + rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession, + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); + if (rc != 0) goto exit; + + printf("NV Auth (%d)\n", authBufSz); + TPM2_PrintBin((const byte*)authBuf, authBufSz); + + for (id = 0; id < keystore_num_pubkeys(); id++) { + TPM_HANDLE handle = nvIndex + id; + uint32_t keyType = keystore_get_key_type(id); + int bufSz = keystore_get_size(id); + byte *buf = keystore_get_buffer(id); + + (void)keyType; /* not used */ + + printf("Computing keystore has for index %d\n", id); + + /* hash public key */ + digestSz = wc_HashGetDigestSize(hashType); + rc = wc_Hash(hashType, buf, (word32)bufSz, digest, digestSz); + if (rc == 0) { + printf("Public Key Hash (%d)\n", digestSz); + TPM2_PrintBin(digest, digestSz); + } + if (rc == 0 && doWrite) { + printf("Storing hash of keystore.c %d to NV index 0x%x\n", + id, handle); + + /* Get NV attributes */ + rc = wolfTPM2_GetNvAttributesTemplate(parent.hndl, &nvAttributes); + if (rc == 0) { + /* allow this NV to be locked */ + nvAttributes |= TPMA_NV_WRITEDEFINE; + + /* Create NV - NV struct populated */ + rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, handle, + nvAttributes, digestSz, (const byte*)authBuf, authBufSz); + if (rc == TPM_RC_NV_DEFINED) { + printf("Warning: NV Index 0x%x already exists!\n", handle); + rc = 0; + } + } + if (rc == 0) { + /* Write digest to NV */ + rc = wolfTPM2_NVWriteAuth(&dev, &nv, handle, digest, digestSz, 0); + } + if (rc == 0) { + printf("Wrote %d bytes to NV 0x%x\n", digestSz, handle); + } + } + + /* Setup a read/lock structure */ + XMEMSET(&nv, 0, sizeof(nv)); + nv.handle.hndl = handle; + nv.handle.auth.size = authBufSz; + XMEMCPY(nv.handle.auth.buffer, authBuf, nv.handle.auth.size); + + if (rc == 0) { + /* Read the NV Index publicArea to have up to date NV Index Name */ + rc = wolfTPM2_NVReadPublic(&dev, nv.handle.hndl, &nvPublic); + } + if (rc == 0) { + digestSz = nvPublic.dataSize; + + /* Read access */ + printf("Reading NV 0x%x public key hash\n", nv.handle.hndl); + rc = wolfTPM2_NVReadAuth(&dev, &nv, nv.handle.hndl, + digest, (word32*)&digestSz, 0); + } + if (rc == 0) { + printf("Read Public Key Hash (%d)\n", digestSz); + TPM2_PrintBin(digest, digestSz); + } + else if ((rc & RC_MAX_FMT1) == TPM_RC_HANDLE) { + printf("NV index does not exist\n"); + } + + if (rc == 0 && doLock) { + printf("Locking NV index 0x%x\n", nv.handle.hndl); + rc = wolfTPM2_NVWriteLock(&dev, &nv); + if (rc == 0) { + printf("NV 0x%x locked\n", nv.handle.hndl); + } + } + + if (rc != 0) goto exit; + } + +exit: + + if (rc != 0) { + printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc)); + } + + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + wolfTPM2_Cleanup(&dev); + + return rc; +} + +int main(int argc, char *argv[]) +{ + /* use platform handle to prevent TPM2_Clear from removing */ + TPMI_RH_NV_AUTH authHandle = TPM_RH_PLATFORM; + word32 nvIndex = TPM2_DEMO_NV_SECURE_ROT_INDEX; + int doWrite = 0, doLock = 0; + enum wc_HashType hashType = WC_HASH_TYPE_SHA256; + const char* authBuf = NULL; + int authBufSz = 0; + + if (argc >= 2) { + if (XSTRCMP(argv[1], "-?") == 0 || + XSTRCMP(argv[1], "-h") == 0 || + XSTRCMP(argv[1], "--help") == 0) { + usage(); + return 0; + } + } + while (argc > 1) { + if (XSTRNCMP(argv[argc-1], "-nvindex=", XSTRLEN("-nvindex=")) == 0) { + const char* nvIndexStr = argv[argc-1] + XSTRLEN("-nvindex="); + nvIndex = (word32)XSTRTOL(nvIndexStr, NULL, 0); + if (!(authHandle == TPM_RH_PLATFORM && ( + nvIndex > TPM_20_PLATFORM_MFG_NV_SPACE && + nvIndex < TPM_20_OWNER_NV_SPACE)) && + !(authHandle == TPM_RH_OWNER && ( + nvIndex > TPM_20_OWNER_NV_SPACE && + nvIndex < TPM_20_TCG_NV_SPACE))) + { + fprintf(stderr, "Invalid NV Index %s\n", nvIndexStr); + fprintf(stderr, "\tPlatform Range: 0x%x -> 0x%x\n", + TPM_20_PLATFORM_MFG_NV_SPACE, TPM_20_OWNER_NV_SPACE); + fprintf(stderr, "\tOwner Range: 0x%x -> 0x%x\n", + TPM_20_OWNER_NV_SPACE, TPM_20_TCG_NV_SPACE); + usage(); + return -1; + } + } + else if (XSTRNCMP(argv[argc-1], "-auth=", XSTRLEN("-auth=")) == 0) { + authBuf = argv[argc-1] + XSTRLEN("-auth="); + authBufSz = (int)XSTRLEN(authBuf); + } + else if (XSTRCMP(argv[argc-1], "-sha384") == 0) { + hashType = WC_HASH_TYPE_SHA384; + } + else if (XSTRCMP(argv[argc-1], "-write") == 0) { + doWrite = 1; + } + else if (XSTRCMP(argv[argc-1], "-lock") == 0) { + doLock = 1; + } + else { + printf("Warning: Unrecognized option: %s\n", argv[argc-1]); + } + argc--; + }; + + return TPM2_Boot_SecureROT_Example( + authHandle, + nvIndex, + hashType, + doWrite, + doLock, + authBuf, authBufSz); +} diff --git a/tools/tpm/user_settings.h b/tools/tpm/user_settings.h new file mode 100644 index 000000000..85d9698be --- /dev/null +++ b/tools/tpm/user_settings.h @@ -0,0 +1,97 @@ +/* user_settings.h + * + * Configuration for wolfBoot TPM tools. + * Enabled via WOLFSSL_USER_SETTINGS. + * + * Copyright (C) 2023 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 _WOLFBOOT_TPM_SETTING_H +#define _WOLFBOOT_TPM_SETTING_H + +#include + +/* TPM Specific Options */ +#define WOLFSSL_PUBLIC_MP +#define WOLFSSL_AES_CFB +#define DEBUG_WOLFTPM /* for TPM2_PrintBin */ + +/* System */ +#define SINGLE_THREADED +#define WOLFCRYPT_ONLY + +/* Math */ +#define WOLFSSL_SP_MATH +#define TFM_TIMING_RESISTANT + +/* ECC */ +#define HAVE_ECC +#define WOLFSSL_HAVE_SP_ECC +#define WOLFSSL_SP_384 +#define WOLFSSL_SP_521 +#define ECC_TIMING_RESISTANT +#define ECC_USER_CURVES +#define HAVE_ECC256 +#define HAVE_ECC384 +#define HAVE_ECC521 + +/* RSA */ +#define HAVE_RSA +#define WOLFSSL_HAVE_SP_RSA +#define WOLFSSL_SP_4096 +#define WC_RSA_BLINDING +#define WOLFSSL_KEY_GEN + +/* Hashing */ +#define WOLFSSL_SHA512 /* Required for ED25519 */ +#define WOLFSSL_SHA384 /* Required for ED25519 */ +#undef NO_SHA256 + +/* ASN */ +#define WOLFSSL_ASN_TEMPLATE +#define WOLFSSL_PEM_TO_DER +#define WOLFSSL_PUB_PEM_TO_DER + +/* Disables */ +#define NO_CMAC +#define NO_RC4 +#define NO_SHA +#define NO_DH +#define NO_DSA +#define NO_MD4 +#define NO_RABBIT +#define NO_MD5 +#define NO_SIG_WRAPPER +#define NO_CERT +#define NO_SESSION_CACHE +#define NO_HC128 +#define NO_DES3 +#define NO_PWDBASED +#define NO_WRITEV +#define NO_MAIN_DRIVER +#define NO_OLD_RNGNAME +#define NO_WOLFSSL_DIR +#define WOLFSSL_NO_SOCK +#define WOLFSSL_IGNORE_FILE_WARN + +#define BENCH_EMBEDDED +#define NO_CRYPT_TEST +#define NO_CRYPT_BENCHMARK + +#endif /* !_WOLFBOOT_TPM_SETTING_H */