Add support for wolfHSM cert chain verification on TC3xx

pull/574/head
Brett Nicholas 2025-05-29 14:46:14 -06:00
parent 23cf367c38
commit d689656a71
11 changed files with 218 additions and 56 deletions

View File

@ -10,6 +10,7 @@ This example demonstrates using wolfBoot on the Infineon AURIX TC3xx family of m
- [Flash Partitioning](#flash-partitioning) - [Flash Partitioning](#flash-partitioning)
- [Standard wolfBoot images](#standard-wolfboot-images) - [Standard wolfBoot images](#standard-wolfboot-images)
- [ELF files](#elf-files) - [ELF files](#elf-files)
- [Cert Chain Verification](#cert-chain-verification)
- [Configuration and the wolfBoot AURIX tool (wbaurixtool.sh)](#configuration-and-the-wolfboot-aurix-tool-wbaurixtoolsh) - [Configuration and the wolfBoot AURIX tool (wbaurixtool.sh)](#configuration-and-the-wolfboot-aurix-tool-wbaurixtoolsh)
- [Building and running the wolfBoot demo](#building-and-running-the-wolfboot-demo) - [Building and running the wolfBoot demo](#building-and-running-the-wolfboot-demo)
- [Prerequisites](#prerequisites) - [Prerequisites](#prerequisites)
@ -23,6 +24,9 @@ This example demonstrates using wolfBoot on the Infineon AURIX TC3xx family of m
- [Load and run the wolfBoot demo in TRACE32](#load-and-run-the-wolfboot-demo-in-trace32) - [Load and run the wolfBoot demo in TRACE32](#load-and-run-the-wolfboot-demo-in-trace32)
- [wolfHSM Compatibility](#wolfhsm-compatibility) - [wolfHSM Compatibility](#wolfhsm-compatibility)
- [Building wolfBoot with wolfHSM](#building-wolfboot-with-wolfhsm) - [Building wolfBoot with wolfHSM](#building-wolfboot-with-wolfhsm)
- [Building wolfBoot with wolfHSM and cert chain verification](#building-wolfboot-with-wolfhsm-and-cert-chain-verification)
- [Custom Certificate Chain](#custom-certificate-chain)
- [Dummy Certificate Chain](#dummy-certificate-chain)
- [Building: Command Sequence](#building-command-sequence) - [Building: Command Sequence](#building-command-sequence)
- [Troubleshooting](#troubleshooting) - [Troubleshooting](#troubleshooting)
- [WSL "bad interpreter" error](#wsl-bad-interpreter-error) - [WSL "bad interpreter" error](#wsl-bad-interpreter-error)
@ -95,6 +99,10 @@ Different linker script templates are used to configure the memory layout via `w
- [test-app (standard wolfBoot images)](test-app/Lcf_Gnu_Tricore_Tc.lsl.in) - [test-app (standard wolfBoot images)](test-app/Lcf_Gnu_Tricore_Tc.lsl.in)
- [test-app (ELF files)](test-app/Lcf_Gnu_Tricore_elf.lsl.in) - [test-app (ELF files)](test-app/Lcf_Gnu_Tricore_elf.lsl.in)
### Cert Chain Verification
wolfBoot on AURIX supports verifying firmware images using certificate chains. For more information on how this wolfBoot feature works, refer to [Signing.md](../../docs/Signing.md), [firmware_update.md](../docs/firmware_update.md), and [wolfBoot-wolfHSM](../../IDE/AURIX/wolfBoot-wolfHSM). Currently this feature can only be used in conjunction with wolfHSM. Instructions for using this feature are detailed below in the [Building wolfBoot with wolfHSM](#building-wolfboot-with-wolfhsm) section.
## Configuration and the wolfBoot AURIX tool (wbaurixtool.sh) ## Configuration and the wolfBoot AURIX tool (wbaurixtool.sh)
wolfBoot relies extensively on its build system in order to properly set configuration macros, linker addresses, and other target-specific items. Because wolfBoot on AURIX uses the AURIX studio IDE to build, changing things like the signature algorithm would require manually editing IDE settings, linker scripts, etc. which is error prone and tedious. The `wbaurixtool.sh` script provides a single tool that automates the generation of all configurable items required for building wolfBoot and the test application on AURIX given the chosen signature and hashing algorithms, including managing all configuration macros, linker scripts, as well as handling the actual key generation and image signing process. `wbaurixtool.sh` can also generate wolfHSM NVM images containing the generated image signing key when used in conjunction with wolfHSM. wolfBoot relies extensively on its build system in order to properly set configuration macros, linker addresses, and other target-specific items. Because wolfBoot on AURIX uses the AURIX studio IDE to build, changing things like the signature algorithm would require manually editing IDE settings, linker scripts, etc. which is error prone and tedious. The `wbaurixtool.sh` script provides a single tool that automates the generation of all configurable items required for building wolfBoot and the test application on AURIX given the chosen signature and hashing algorithms, including managing all configuration macros, linker scripts, as well as handling the actual key generation and image signing process. `wbaurixtool.sh` can also generate wolfHSM NVM images containing the generated image signing key when used in conjunction with wolfHSM.
@ -320,6 +328,27 @@ IDE/AURIX/wolfHSM-infineon-tc3xx/
3. Provide the `--hsm` global option to the `wbaurixtool.sh` script when invoking it so that the wolfHSM projects are used instead of the standard wolfBoot projects 3. Provide the `--hsm` global option to the `wbaurixtool.sh` script when invoking it so that the wolfHSM projects are used instead of the standard wolfBoot projects
4. If using the default build options in [wolfBoot-tc3xx-wolfHSM](./wolfBoot-tc3xx-wolfHSM/), wolfBoot will expect the public key for image verification to be stored at a specific keyId for the wolfBoot client ID. You can use [whnvmtool](https://github.com/wolfSSL/wolfHSM/tree/main/tools/whnvmtool) to generate a loadable NVM image that contains the required keys automatically via `wbaurixtool.sh` through the `nvm` subcommand. This generates an NVM image containing the generated image signing key based on the [wolfBoot-wolfHSM-keys.nvminit](../../tools/scripts/tc3xx/wolfBoot-wolfHSM-keys.nvminit) configuration file, which can then be loaded to the device via a flash programming tool. Before using the `nvm` subcommand of `wbaurixtool.sh`, first compile `whnvmtool` by running `make` in the `lib/wolfHSM/tools/whnvmtool` directory. See the `whnvmtool` documentation and the documentation included in your wolfHSM AURIX release for more details. Note: if you want to use the standard wolfBoot keystore functionality in conjunction with wolfHSM for testing purposes (doesn't require pre-loading keys on the HSM) you can configure wolfBoot to send the keys to the HSM on-the-fly as ephemeral keys. To do this, ensure `WOLFBOOT_USE_WOLFHSM_PUBKEY_ID` is **NOT** defined, and add the `--localkeys` argument to then `./wbaurixtool.sh keygen` command, which invokes the `keygen` tool without the default `--nolocalkeys` option. 4. If using the default build options in [wolfBoot-tc3xx-wolfHSM](./wolfBoot-tc3xx-wolfHSM/), wolfBoot will expect the public key for image verification to be stored at a specific keyId for the wolfBoot client ID. You can use [whnvmtool](https://github.com/wolfSSL/wolfHSM/tree/main/tools/whnvmtool) to generate a loadable NVM image that contains the required keys automatically via `wbaurixtool.sh` through the `nvm` subcommand. This generates an NVM image containing the generated image signing key based on the [wolfBoot-wolfHSM-keys.nvminit](../../tools/scripts/tc3xx/wolfBoot-wolfHSM-keys.nvminit) configuration file, which can then be loaded to the device via a flash programming tool. Before using the `nvm` subcommand of `wbaurixtool.sh`, first compile `whnvmtool` by running `make` in the `lib/wolfHSM/tools/whnvmtool` directory. See the `whnvmtool` documentation and the documentation included in your wolfHSM AURIX release for more details. Note: if you want to use the standard wolfBoot keystore functionality in conjunction with wolfHSM for testing purposes (doesn't require pre-loading keys on the HSM) you can configure wolfBoot to send the keys to the HSM on-the-fly as ephemeral keys. To do this, ensure `WOLFBOOT_USE_WOLFHSM_PUBKEY_ID` is **NOT** defined, and add the `--localkeys` argument to then `./wbaurixtool.sh keygen` command, which invokes the `keygen` tool without the default `--nolocalkeys` option.
### Building wolfBoot with wolfHSM and cert chain verification
wolfBoot with wolfHSM supports certificate chain verification for firmware images. This feature allows wolfBoot to verify that firmware images are signed with certificates that can be traced back to a trusted root certificate authority through a certificate chain.
The `wbaurixtool.sh` script provides two options for applicable commands that enable automation of configuring the build for certificate chain verification:
- `--certchain <file>`: Use a user-provided certificate chain file
- `--dummy-certchain`: Use a "dummy" certificate chain that is created from the key pair generated by the wolfBoot keytools for development/testing purposes.
Both options require the `--hsm` global option and can be used with the `keygen`, `sign`, `macros`, `lcf`, and `nvm` subcommands.
### Custom Certificate Chain
If you want to use a custom certificate chain for verification, you can provide the `--certchain <certchain file>` option to the `macros`, `lcf`, and `sign` subcommands. This ensures that your certificate chain will be included in the generated firmware image and that wolfBoot will verify the chain on boot, then verify the signature of the firmware image using the public key corresponding to the leaf certificate in the chain. Note that the user is responsible for properly constructing the certificate chain and ensuring that the leaf certificate is bound to the firmware signing key pair, as well as properly provisioning the HSM with the root CA certificate at the expected NVM object ID specified by the HAL.
### Dummy Certificate Chain
If you just want to test out the certificate verifcation functionality, `wbaurixtool.sh` can generate and use a dummy certificate chain by providing the `--dummy-certchain` option to the `keygen`, `sign`, `macros`, `lcf`, and `nvm` subcommands. This will cause the keygen step to generate a dummy root CA at `test-dummy-ca/root-ca.der`, well as a dummy certificate chain at `test-dummy-ca/raw-chain.der` using the specified algorithm. The generated chain consists of a single intermediate as well as a leaf (signing) certificate whose identity is bound to the generated firmware signing key pair. The subsequent commands will then ensure this generated chain is used by wolfBoot. Additionally, the `nvm` subcommand will create an NVM image containing the generated root CA that can be loaded into HSM NVM.
**Note: The `--dummy-certchain` option is intended for development and testing. For production use, generate and use your own certificate chain.**
## Building: Command Sequence ## Building: Command Sequence
The following pseudo command sequence shows a brief overview of the commands needed to build wolfBoot on AURIX (optionally with wolfHSM). The signature and hashing algorithms used in the example are ECC 256 and SHA 256 and specified explicitly for clarity. Note that these algorithms are the default, so do not need to be explicitly specified. Optional arguments are shown in square brackets (e.g. if targeting wolfHSM, the `--hsm` option must be provided as a global option to `wbaurixtool.sh`). The following pseudo command sequence shows a brief overview of the commands needed to build wolfBoot on AURIX (optionally with wolfHSM). The signature and hashing algorithms used in the example are ECC 256 and SHA 256 and specified explicitly for clarity. Note that these algorithms are the default, so do not need to be explicitly specified. Optional arguments are shown in square brackets (e.g. if targeting wolfHSM, the `--hsm` option must be provided as a global option to `wbaurixtool.sh`).

File diff suppressed because one or more lines are too long

View File

@ -7,4 +7,5 @@
@ML_DSA_LEVEL@ @ML_DSA_LEVEL@
@ML_DSA_IMAGE_SIGNATURE_SIZE@ @ML_DSA_IMAGE_SIGNATURE_SIZE@
@WOLFBOOT_ELF@ @WOLFBOOT_ELF@
@WOLFBOOT_ELF_FLASH_SCATTER@ @WOLFBOOT_ELF_FLASH_SCATTER@
@WOLFBOOT_CERT_CHAIN_VERIFY@

View File

@ -26,5 +26,6 @@
#define WOLFHSM_CFG_H_ #define WOLFHSM_CFG_H_
#define WOLFHSM_CFG_DMA #define WOLFHSM_CFG_DMA
#define WOLFHSM_CFG_CERTIFICATE_MANAGER
#endif /* WOLFHSM_CFG_H_ */ #endif /* WOLFHSM_CFG_H_ */

File diff suppressed because one or more lines are too long

View File

@ -665,6 +665,9 @@ const int hsmClientKeyIdPubKey = 0xFF;
const int hsmClientDevIdCrypt = WH_DEV_ID; const int hsmClientDevIdCrypt = WH_DEV_ID;
const int hsmClientKeyIdCrypt = 0xFF; const int hsmClientKeyIdCrypt = 0xFF;
#endif #endif
#ifdef WOLFBOOT_CERT_CHAIN_VERIFY
const whNvmId hsmClientNvmIdCertRootCA = 1;
#endif
static int _cancelCb(uint16_t cancelSeq) static int _cancelCb(uint16_t cancelSeq)

View File

@ -928,7 +928,7 @@ ifneq ($(CERT_CHAIN_VERIFY),)
KEYGEN_OPTIONS += --der KEYGEN_OPTIONS += --der
ifneq ($(CERT_CHAIN_GEN),) ifneq ($(CERT_CHAIN_GEN),)
# Use dummy cert chain file if not provided (needs to be generated when keys are generated) # Use dummy cert chain file if not provided (needs to be generated when keys are generated)
CERT_CHAIN_FILE = test-dummy-ca/raw_chain.der CERT_CHAIN_FILE = test-dummy-ca/raw-chain.der
# Set appropriate cert gen options based on sigalg # Set appropriate cert gen options based on sigalg
ifeq ($(SIGN),ECC256) ifeq ($(SIGN),ECC256)

View File

@ -2038,10 +2038,20 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
wolfBoot_printf("Found certificate chain (%d bytes)\n", wolfBoot_printf("Found certificate chain (%d bytes)\n",
cert_chain_size); cert_chain_size);
/* Verify certificate chain using wolfHSM's verification API */ /* Verify certificate chain using wolfHSM's verification API. Use DMA if
* available in the wolfHSM configuration */
#if defined(WOLFHSM_CFG_DMA)
wolfBoot_printf(
"verifying cert chain and caching leaf pubkey (using DMA)\n");
hsm_ret = wh_Client_CertVerifyDmaAndCacheLeafPubKey(
&hsmClientCtx, cert_chain, cert_chain_size,
hsmClientNvmIdCertRootCA, &g_certLeafKeyId, &cert_verify_result);
#else
wolfBoot_printf("verifying cert chain and caching leaf pubkey\n");
hsm_ret = wh_Client_CertVerifyAndCacheLeafPubKey( hsm_ret = wh_Client_CertVerifyAndCacheLeafPubKey(
&hsmClientCtx, cert_chain, cert_chain_size, &hsmClientCtx, cert_chain, cert_chain_size,
hsmClientNvmIdCertRootCA, &g_certLeafKeyId, &cert_verify_result); hsmClientNvmIdCertRootCA, &g_certLeafKeyId, &cert_verify_result);
#endif
/* Error or verification failure results in standard auth check failure /* Error or verification failure results in standard auth check failure
* path */ * path */

View File

@ -176,7 +176,7 @@ echo "Extracting public key from leaf certificate..."
extract_public_key "${OUTPUT_DIR}/temp/leaf.crt.pem" "${OUTPUT_DIR}/temp/leaf_pubkey.pem" "${OUTPUT_DIR}/leaf-pubkey.der" extract_public_key "${OUTPUT_DIR}/temp/leaf.crt.pem" "${OUTPUT_DIR}/temp/leaf_pubkey.pem" "${OUTPUT_DIR}/leaf-pubkey.der"
# Create raw DER format certificate chain # Create raw DER format certificate chain
cat ${OUTPUT_DIR}/intermediate-cert.der ${OUTPUT_DIR}/leaf-cert.der > ${OUTPUT_DIR}/raw_chain.der cat ${OUTPUT_DIR}/intermediate-cert.der ${OUTPUT_DIR}/leaf-cert.der > ${OUTPUT_DIR}/raw-chain.der
################################## ##################################
# GENERATE C ARRAYS FOR EMBEDDING # GENERATE C ARRAYS FOR EMBEDDING
@ -223,7 +223,7 @@ echo "/* Certificates */" >> "${HEADER_FILE}"
append_cert_array "${OUTPUT_DIR}/root-cert.der" "ROOT_CERT" "Root CA Certificate (DER format)" append_cert_array "${OUTPUT_DIR}/root-cert.der" "ROOT_CERT" "Root CA Certificate (DER format)"
append_cert_array "${OUTPUT_DIR}/intermediate-cert.der" "INTERMEDIATE_CERT" "Intermediate CA Certificate (DER format)" append_cert_array "${OUTPUT_DIR}/intermediate-cert.der" "INTERMEDIATE_CERT" "Intermediate CA Certificate (DER format)"
append_cert_array "${OUTPUT_DIR}/leaf-cert.der" "LEAF_CERT" "Leaf/Server Certificate (DER format)" append_cert_array "${OUTPUT_DIR}/leaf-cert.der" "LEAF_CERT" "Leaf/Server Certificate (DER format)"
append_cert_array "${OUTPUT_DIR}/raw_chain.der" "RAW_CERT_CHAIN" "Raw Certificate Chain (Intermediate+Leaf) (DER format)" append_cert_array "${OUTPUT_DIR}/raw-chain.der" "RAW_CERT_CHAIN" "Raw Certificate Chain (Intermediate+Leaf) (DER format)"
# Add leaf certificate public key # Add leaf certificate public key
append_cert_array "${OUTPUT_DIR}/leaf-pubkey.der" "LEAF_PUBKEY" "Leaf Certificate Public Key (DER format)" append_cert_array "${OUTPUT_DIR}/leaf-pubkey.der" "LEAF_PUBKEY" "Leaf Certificate Public Key (DER format)"
@ -257,7 +257,7 @@ echo " Intermediate certificate: ${OUTPUT_DIR}/intermediate-cert.der"
echo " Intermediate key: ${OUTPUT_DIR}/intermediate-prvkey.der" echo " Intermediate key: ${OUTPUT_DIR}/intermediate-prvkey.der"
echo " Leaf certificate: ${OUTPUT_DIR}/leaf-cert.der" echo " Leaf certificate: ${OUTPUT_DIR}/leaf-cert.der"
echo " Leaf key: ${OUTPUT_DIR}/leaf-prvkey.der" echo " Leaf key: ${OUTPUT_DIR}/leaf-prvkey.der"
echo " Raw chain: ${OUTPUT_DIR}/raw_chain.der" echo " Raw chain: ${OUTPUT_DIR}/raw-chain.der"
echo " Leaf public key: ${OUTPUT_DIR}/leaf-pubkey.der" echo " Leaf public key: ${OUTPUT_DIR}/leaf-pubkey.der"
echo "" echo ""
echo "C Header file:" echo "C Header file:"

View File

@ -27,8 +27,10 @@ PRVKEY_DER="$WOLFBOOT_DIR/priv.der"
PUBKEY_DER="$WOLFBOOT_DIR/priv_pub.der" PUBKEY_DER="$WOLFBOOT_DIR/priv_pub.der"
TARGET_H="$WOLFBOOT_DIR/include/target.h" TARGET_H="$WOLFBOOT_DIR/include/target.h"
NVM_CONFIG="$WOLFBOOT_DIR/tools/scripts/tc3xx/wolfBoot-wolfHSM-keys.nvminit" NVM_CONFIG="$WOLFBOOT_DIR/tools/scripts/tc3xx/wolfBoot-wolfHSM-keys.nvminit"
NVM_CONFIG_DUMMY_CERTCHAIN="$WOLFBOOT_DIR/tools/scripts/tc3xx/wolfBoot-wolfHSM-dummy-certchain.nvminit"
NVM_BIN="whNvmImage.bin" NVM_BIN="whNvmImage.bin"
NVM_HEX="whNvmImage.hex" NVM_HEX="whNvmImage.hex"
DUMMY_CERT_CHAIN="$WOLFBOOT_DIR/test-dummy-ca/raw-chain.der"
# Tool paths (relative to project root) # Tool paths (relative to project root)
SQUASHELF="$WOLFBOOT_DIR/tools/squashelf/squashelf" SQUASHELF="$WOLFBOOT_DIR/tools/squashelf/squashelf"
@ -93,30 +95,11 @@ declare -A ML_DSA_HEADER_SIZES=(
[5]=12288 [5]=12288
) )
# Get the header size based on the selected public key algorithm
get_header_size() {
local algo="$1"
local pq_params="$2"
case "$algo" in
"ml_dsa")
# Default to level 2 for ML-DSA if no params specified
echo "${ML_DSA_HEADER_SIZES[${pq_params:-2}]}"
;;
"ecc256") echo "256" ;;
"ecc384"|"ecc521"|"rsa2048"|"rsa3072") echo "512" ;;
"rsa4096") echo "1024" ;;
"ed25519") echo "256" ;;
"ed448") echo "512" ;;
"lms"|"xmss") echo "0" ;; # currently not supported
"none") echo "256" ;;
*) echo "256" ;; # Default
esac
}
# Add to command options structure # Add to command options structure
declare -A COMMON_OPTS=( declare -A COMMON_OPTS=(
[sign_pq_params]="" [sign_pq_params]=""
[certchain_file]=""
[dummy_certchain]=""
) )
# Add LCF_OPTS to command options structure # Add LCF_OPTS to command options structure
@ -130,6 +113,80 @@ declare -A TARGET_OPTS=(
[use_elf_format]="" [use_elf_format]=""
) )
# Add NVM_OPTS to command options structure
declare -A NVM_OPTS=(
[dummy_certchain]=""
)
# Get the effective certificate chain file path
get_effective_certchain_file() {
if [[ -n "${COMMON_OPTS[dummy_certchain]}" ]]; then
echo "$DUMMY_CERT_CHAIN"
elif [[ -n "${COMMON_OPTS[certchain_file]}" ]]; then
echo "${COMMON_OPTS[certchain_file]}"
else
echo ""
fi
}
# Get the header size based on the selected public key algorithm
get_header_size() {
local algo="$1"
local pq_params="$2"
local certchain_file="$3"
# Get base header size for the algorithm
local base_size
case "$algo" in
"ml_dsa")
# Default to level 2 for ML-DSA if no params specified
base_size="${ML_DSA_HEADER_SIZES[${pq_params:-2}]}"
;;
"ecc256") base_size="256" ;;
"ecc384"|"ecc521"|"rsa2048"|"rsa3072") base_size="512" ;;
"rsa4096") base_size="1024" ;;
"ed25519") base_size="256" ;;
"ed448") base_size="512" ;;
"lms"|"xmss") base_size="0" ;; # currently not supported
"none") base_size="256" ;;
*) base_size="256" ;; # Default
esac
# If no certificate chain, return base size
if [[ -z "$certchain_file" ]]; then
echo "$base_size"
return
fi
# Check if certificate chain file exists and get its size
if [[ ! -f "$certchain_file" ]]; then
echo "Error: Certificate chain file not found: $certchain_file" >&2
echo "$base_size"
return
fi
local cert_size
cert_size=$(stat -c%s "$certchain_file" 2>/dev/null || stat -f%z "$certchain_file" 2>/dev/null)
if [[ $? -ne 0 ]]; then
echo "Error: Cannot get certificate chain file size: $certchain_file" >&2
echo "$base_size"
return
fi
# Calculate total required space
# cert_size + 4 bytes (TLV header) + 8 bytes (max alignment padding)
local cert_overhead=$((cert_size + 12))
local total_required=$((base_size + cert_overhead))
# Round up to next power of 2 (matching C code behavior)
local final_size=$base_size
while [[ $final_size -lt $total_required ]]; do
final_size=$((final_size * 2))
done
echo "$final_size"
}
# Helper function to display usage # Helper function to display usage
usage() { usage() {
echo "Usage: $0 [global-options] COMMAND [command-options] [COMMAND [command-options]]" echo "Usage: $0 [global-options] COMMAND [command-options] [COMMAND [command-options]]"
@ -142,11 +199,14 @@ usage() {
echo " keygen" echo " keygen"
echo " --sign-algo ALGO Signing algorithm (default: ecc256)" echo " --sign-algo ALGO Signing algorithm (default: ecc256)"
echo " --localkeys Use local keys (only valid with --hsm)" echo " --localkeys Use local keys (only valid with --hsm)"
echo " --dummy-certchain Generate dummy certificate chain after key generation"
echo "" echo ""
echo " sign" echo " sign"
echo " --sign-algo ALGO Signing algorithm (inherits from keygen if not specified)" echo " --sign-algo ALGO Signing algorithm (inherits from keygen if not specified)"
echo " --hash-algo ALGO Hash algorithm (default: sha256)" echo " --hash-algo ALGO Hash algorithm (default: sha256)"
echo " --debug Use debug build (default: release)" echo " --debug Use debug build (default: release)"
echo " --certchain FILE Certificate chain file to include in header"
echo " --dummy-certchain Use dummy certificate chain in header"
echo "" echo ""
echo " target" echo " target"
echo " No additional options" echo " No additional options"
@ -157,12 +217,16 @@ usage() {
echo " macros" echo " macros"
echo " --sign-algo ALGO Signing algorithm (inherits from keygen/sign if not specified)" echo " --sign-algo ALGO Signing algorithm (inherits from keygen/sign if not specified)"
echo " --hash-algo ALGO Hash algorithm (inherits from sign if not specified)" echo " --hash-algo ALGO Hash algorithm (inherits from sign if not specified)"
echo " --certchain FILE Certificate chain file to include in header"
echo " --dummy-certchain Use dummy certificate chain in header"
echo "" echo ""
echo " nvm" echo " nvm"
echo " No additional options" echo " --dummy-certchain Use dummy certificate chain configuration"
echo "" echo ""
echo " lcf" echo " lcf"
echo " --sign-algo ALGO Signing algorithm (inherits from keygen/sign if not specified)" echo " --sign-algo ALGO Signing algorithm (inherits from keygen/sign if not specified)"
echo " --certchain FILE Certificate chain file to include in header"
echo " --dummy-certchain Use dummy certificate chain in header"
echo "" echo ""
echo "Examples:" echo "Examples:"
echo " $0 keygen --sign-algo ecc256" echo " $0 keygen --sign-algo ecc256"
@ -174,28 +238,29 @@ usage() {
echo " $0 macros" echo " $0 macros"
echo " $0 nvm" echo " $0 nvm"
echo " $0 lcf" echo " $0 lcf"
echo " $0 sign --certchain /path/to/cert_chain.pem"
echo " $0 macros --certchain /path/to/cert_chain.pem lcf --certchain /path/to/cert_chain.pem"
echo " $0 keygen --sign-algo ecc256 --dummy-certchain"
echo " $0 sign --dummy-certchain"
echo " $0 keygen --sign-algo ecc256 --dummy-certchain sign --dummy-certchain"
echo " $0 nvm --dummy-certchain"
exit 1 exit 1
} }
# Function to generate keys # Function to generate keys
do_keygen() { do_keygen() {
local sign_algo="${KEYGEN_OPTS[sign_algo]:-$DEFAULT_SIGN_ALGO}" local sign_algo="${KEYGEN_OPTS[sign_algo]:-$DEFAULT_SIGN_ALGO}"
local pq_params="${COMMON_OPTS[sign_pq_params]}"
local header_size
# Get header size for current algorithm
header_size=$(get_header_size "$sign_algo" "$pq_params")
echo "Generating keys with algorithm: $sign_algo" echo "Generating keys with algorithm: $sign_algo"
# Set environment variables for keygen tool
export IMAGE_HEADER_SIZE="$header_size"
if [ "$sign_algo" = "ml_dsa" ]; then
export ML_DSA_LEVEL="${pq_params:-2}" # Default to level 2 if not specified
fi
(cd $WOLFBOOT_DIR && tools/keytools/keygen --"$sign_algo" -g $(basename $PRVKEY_DER) --exportpubkey \ (cd $WOLFBOOT_DIR && tools/keytools/keygen --"$sign_algo" -g $(basename $PRVKEY_DER) --exportpubkey \
${KEYGEN_OPTS[nolocalkeys]:+--nolocalkeys} --der) ${KEYGEN_OPTS[nolocalkeys]:+--nolocalkeys} --der)
# Generate dummy certificate chain if requested
if [[ -n "${COMMON_OPTS[dummy_certchain]}" ]]; then
echo "Generating dummy certificate chain with algorithm: $sign_algo"
(cd $WOLFBOOT_DIR && tools/scripts/sim-gen-dummy-chain.sh --algo "$sign_algo" --leaf priv.der)
fi
} }
# Function to sign binaries # Function to sign binaries
@ -218,7 +283,7 @@ do_sign() {
fi fi
# Get header size for current algorithm # Get header size for current algorithm
header_size=$(get_header_size "$sign_algo" "$pq_params") header_size=$(get_header_size "$sign_algo" "$pq_params" "$(get_effective_certchain_file)")
# Set IMAGE_HEADER_SIZE environment variable for sign tool # Set IMAGE_HEADER_SIZE environment variable for sign tool
export IMAGE_HEADER_SIZE="$header_size" export IMAGE_HEADER_SIZE="$header_size"
@ -226,9 +291,17 @@ do_sign() {
echo "Signing binaries with $sign_algo and ${SIGN_OPTS[hash_algo]}" echo "Signing binaries with $sign_algo and ${SIGN_OPTS[hash_algo]}"
echo "Using header size: $header_size" echo "Using header size: $header_size"
# Build cert-chain argument if specified
local cert_chain_arg=""
if [[ -n "${COMMON_OPTS[certchain_file]}" ]]; then
cert_chain_arg="--cert-chain ${COMMON_OPTS[certchain_file]}"
elif [[ -n "${COMMON_OPTS[dummy_certchain]}" ]]; then
cert_chain_arg="--cert-chain $DUMMY_CERT_CHAIN"
fi
# Sign for both partition 1 and 2 # Sign for both partition 1 and 2
../../keytools/sign --"$sign_algo" --"${SIGN_OPTS[hash_algo]}" "$bin_path" "$PRVKEY_DER" 1 ../../keytools/sign --"$sign_algo" --"${SIGN_OPTS[hash_algo]}" $cert_chain_arg "$bin_path" "$PRVKEY_DER" 1
../../keytools/sign --"$sign_algo" --"${SIGN_OPTS[hash_algo]}" "$bin_path" "$PRVKEY_DER" 2 ../../keytools/sign --"$sign_algo" --"${SIGN_OPTS[hash_algo]}" $cert_chain_arg "$bin_path" "$PRVKEY_DER" 2
} }
# Function to generate target header # Function to generate target header
@ -303,7 +376,8 @@ do_gen_macros() {
local pq_params="${COMMON_OPTS[sign_pq_params]}" local pq_params="${COMMON_OPTS[sign_pq_params]}"
# Get header size using the new function # Get header size using the new function
local image_header_size=$(get_header_size "$sign_algo" "$pq_params") local image_header_size=$(get_header_size "$sign_algo" "$pq_params" "$(get_effective_certchain_file)")
echo "generating macros with header size = $image_header_size"
local use_huge_stack="" local use_huge_stack=""
local use_wolfhsm_pubkey_id="" local use_wolfhsm_pubkey_id=""
@ -312,6 +386,7 @@ do_gen_macros() {
local ml_dsa_level="" local ml_dsa_level=""
local use_wolfboot_elf="" local use_wolfboot_elf=""
local use_wolfboot_elf_flash_scattered="" local use_wolfboot_elf_flash_scattered=""
local use_wolfboot_cert_chain_verify=""
# Map algorithms to their macro names # Map algorithms to their macro names
local sign_macro="${SIGN_ALGO_MAP[${sign_algo,,}]:-}" local sign_macro="${SIGN_ALGO_MAP[${sign_algo,,}]:-}"
@ -326,6 +401,13 @@ do_gen_macros() {
exit 1 exit 1
fi fi
# Validate certificate chain usage
if [[ -n "${COMMON_OPTS[certchain_file]}" ]]; then
use_wolfboot_cert_chain_verify="-DWOLFBOOT_CERT_CHAIN_VERIFY"
elif [[ -n "${COMMON_OPTS[dummy_certchain]}" ]]; then
use_wolfboot_cert_chain_verify="-DWOLFBOOT_CERT_CHAIN_VERIFY"
fi
# Set huge stack for RSA4096 # Set huge stack for RSA4096
if [[ "${sign_algo,,}" == "rsa4096" ]]; then if [[ "${sign_algo,,}" == "rsa4096" ]]; then
use_huge_stack="-DWOLFBOOT_HUGE_STACK" use_huge_stack="-DWOLFBOOT_HUGE_STACK"
@ -373,6 +455,7 @@ do_gen_macros() {
-e "s/@WOLFBOOT_USE_WOLFHSM_PUBKEY_ID@/$use_wolfhsm_pubkey_id/g" \ -e "s/@WOLFBOOT_USE_WOLFHSM_PUBKEY_ID@/$use_wolfhsm_pubkey_id/g" \
-e "s/@WOLFBOOT_ELF@/$use_wolfboot_elf/g" \ -e "s/@WOLFBOOT_ELF@/$use_wolfboot_elf/g" \
-e "s/@WOLFBOOT_ELF_FLASH_SCATTER@/$use_wolfboot_elf_flash_scattered/g" \ -e "s/@WOLFBOOT_ELF_FLASH_SCATTER@/$use_wolfboot_elf_flash_scattered/g" \
-e "s/@WOLFBOOT_CERT_CHAIN_VERIFY@/$use_wolfboot_cert_chain_verify/g" \
"$macros_in" > "$macros_out" "$macros_in" > "$macros_out"
# Remove empty lines from the output file, as they cause compiler errors # Remove empty lines from the output file, as they cause compiler errors
@ -381,9 +464,16 @@ do_gen_macros() {
# Function to generate a wolfHSM NVM image # Function to generate a wolfHSM NVM image
do_gen_nvm() { do_gen_nvm() {
local nvm_config_file="$NVM_CONFIG"
# Use dummy cert chain config if specified
if [[ -n "${COMMON_OPTS[dummy_certchain]}" ]]; then
nvm_config_file="$NVM_CONFIG_DUMMY_CERTCHAIN"
fi
echo "Generating HSM NVM image" echo "Generating HSM NVM image"
echo "Running: $WHNVMTOOL --image=$NVM_BIN --size=0x10000 --invert-erased-byte $NVM_CONFIG" echo "Running: $WHNVMTOOL --image=$NVM_BIN --size=0x10000 --invert-erased-byte $nvm_config_file"
"$WHNVMTOOL" --image="$NVM_BIN" --size=0x10000 --invert-erased-byte "$NVM_CONFIG" "$WHNVMTOOL" --image="$NVM_BIN" --size=0x10000 --invert-erased-byte "$nvm_config_file"
echo "Converting to Intel HEX format" echo "Converting to Intel HEX format"
echo "Running: objcopy -I binary -O ihex --change-address 0xAFC00000 $NVM_BIN $NVM_HEX" echo "Running: objcopy -I binary -O ihex --change-address 0xAFC00000 $NVM_BIN $NVM_HEX"
@ -412,7 +502,7 @@ do_gen_lcf() {
local lcf_template="$base_dir/$app_dir/$template_name" local lcf_template="$base_dir/$app_dir/$template_name"
local lcf_output="$base_dir/$app_dir/Lcf_Gnuc_Tricore_Tc.lsl" local lcf_output="$base_dir/$app_dir/Lcf_Gnuc_Tricore_Tc.lsl"
header_size=$(get_header_size "$sign_algo" "$pq_params") header_size=$(get_header_size "$sign_algo" "$pq_params" "$(get_effective_certchain_file)")
echo "Generating LCF file with header_size=$header_size" echo "Generating LCF file with header_size=$header_size"
sed -e "s/@LCF_WOLFBOOT_HEADER_OFFSET@/$header_size/g" \ sed -e "s/@LCF_WOLFBOOT_HEADER_OFFSET@/$header_size/g" \
@ -479,7 +569,7 @@ while [[ $# -gt 0 ]]; do
;; ;;
nvm) nvm)
OPERATIONS+=("nvm") OPERATIONS+=("nvm")
CURRENT_OPTS="" CURRENT_OPTS="NVM_OPTS"
shift shift
;; ;;
lcf) lcf)
@ -546,6 +636,26 @@ while [[ $# -gt 0 ]]; do
COMMON_OPTS[sign_pq_params]="$2" COMMON_OPTS[sign_pq_params]="$2"
shift 2 shift 2
;; ;;
--certchain)
if [[ -z "$CURRENT_OPTS" ]]; then
echo "Error: --certchain must follow a command"
exit 1
fi
if [[ -z "$HSM" ]]; then
echo "Error: --certchain can only be used with --hsm global option"
exit 1
fi
COMMON_OPTS[certchain_file]="$2"
shift 2
;;
--dummy-certchain)
if [[ -z "$CURRENT_OPTS" ]]; then
echo "Error: --dummy-certchain must follow a command"
exit 1
fi
COMMON_OPTS[dummy_certchain]="1"
shift
;;
*) *)
echo "Unknown option for ${CURRENT_OPTS:-global options}: $1" echo "Unknown option for ${CURRENT_OPTS:-global options}: $1"
usage usage
@ -559,6 +669,12 @@ if [ ${#OPERATIONS[@]} -eq 0 ]; then
usage usage
fi fi
# Validate that --certchain and --dummy-certchain are not both specified
if [[ -n "${COMMON_OPTS[certchain_file]}" && -n "${COMMON_OPTS[dummy_certchain]}" ]]; then
echo "Error: Cannot specify both --certchain and --dummy-certchain"
exit 1
fi
# Execute requested operations in order # Execute requested operations in order
for op in "${OPERATIONS[@]}"; do for op in "${OPERATIONS[@]}"; do
case $op in case $op in

View File

@ -0,0 +1,2 @@
# NVM config file for wolfHSM whnvmtool to create NVM image based on generated keys
obj 1 0xFFFF 0x0000 "cert CA" ../../../test-dummy-ca/root-cert.der