mirror of https://github.com/wolfSSL/wolfBoot.git
704 lines
24 KiB
Bash
704 lines
24 KiB
Bash
#!/bin/bash
|
|
|
|
# wbaurixtool.sh - wolfBoot AURIX TC3xx Build Tool
|
|
#
|
|
# This tool provides a unified interface for building and signing wolfBoot images
|
|
# for the AURIX TC3xx platform. It handles:
|
|
#
|
|
# - Generating the appropriate wolfBoot configuration macros based on the selected
|
|
# signature algorithm
|
|
# - Generating linker files (LCF) compatible with the selected build options
|
|
# - Key generation
|
|
# - Signing firmware images
|
|
# - Creating HSM NVM images when using wolfHSM
|
|
#
|
|
# This tool can be used with or without wolfHSM integration.
|
|
#
|
|
# Usage: ./wbaurixtool.sh <operation> [options]
|
|
# Operations: keygen, sign, macros, lcf, clean, target, nvm
|
|
# Run with -h for detailed help on available options
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
# File paths (relative to project root)
|
|
WOLFBOOT_DIR="../../../"
|
|
PRVKEY_DER="$WOLFBOOT_DIR/priv.der"
|
|
PUBKEY_DER="$WOLFBOOT_DIR/priv_pub.der"
|
|
TARGET_H="$WOLFBOOT_DIR/include/target.h"
|
|
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_HEX="whNvmImage.hex"
|
|
DUMMY_CERT_CHAIN="$WOLFBOOT_DIR/test-dummy-ca/raw-chain.der"
|
|
|
|
# Tool paths (relative to project root)
|
|
SQUASHELF="$WOLFBOOT_DIR/tools/squashelf/squashelf"
|
|
WHNVMTOOL="$WOLFBOOT_DIR/lib/wolfHSM/tools/whnvmtool/whnvmtool"
|
|
|
|
# Default algorithm configuration
|
|
DEFAULT_SIGN_ALGO="ecc256"
|
|
DEFAULT_HASH_ALGO="sha256"
|
|
|
|
# Default values
|
|
HSM=""
|
|
ELF=""
|
|
OPERATIONS=()
|
|
|
|
# Important Constants
|
|
PFLASH1_RANGE="0xA0300000-0xA0500000"
|
|
|
|
# Structure to hold command options
|
|
declare -A KEYGEN_OPTS=(
|
|
[sign_algo]="$DEFAULT_SIGN_ALGO"
|
|
[nolocalkeys]=""
|
|
)
|
|
declare -A SIGN_OPTS=(
|
|
[sign_algo]="$DEFAULT_SIGN_ALGO"
|
|
[hash_algo]="$DEFAULT_HASH_ALGO"
|
|
[build_type]="Release"
|
|
[file_ext]=".bin"
|
|
)
|
|
declare -A MACROS_OPTS=(
|
|
[sign_algo]=""
|
|
[hash_algo]=""
|
|
[use_elf_format]=""
|
|
)
|
|
CURRENT_OPTS=""
|
|
|
|
# Add the mapping dictionaries
|
|
declare -A HASH_ALGO_MAP=(
|
|
["sha256"]="WOLFBOOT_HASH_SHA256"
|
|
["sha384"]="WOLFBOOT_HASH_SHA384"
|
|
["sha3"]="WOLFBOOT_HASH_SHA3_384"
|
|
)
|
|
|
|
declare -A SIGN_ALGO_MAP=(
|
|
["ed25519"]="WOLFBOOT_SIGN_ED25519"
|
|
["ed448"]="WOLFBOOT_SIGN_ED448"
|
|
["ecc256"]="WOLFBOOT_SIGN_ECC256"
|
|
["ecc384"]="WOLFBOOT_SIGN_ECC384"
|
|
["ecc521"]="WOLFBOOT_SIGN_ECC521"
|
|
["rsa2048"]="WOLFBOOT_SIGN_RSA2048"
|
|
["rsa3072"]="WOLFBOOT_SIGN_RSA3072"
|
|
["rsa4096"]="WOLFBOOT_SIGN_RSA4096"
|
|
["lms"]="WOLFBOOT_SIGN_LMS"
|
|
["xmss"]="WOLFBOOT_SIGN_XMSS"
|
|
["ml_dsa"]="WOLFBOOT_SIGN_ML_DSA"
|
|
["none"]="WOLFBOOT_NO_SIGN"
|
|
)
|
|
|
|
# Add nested map for ML-DSA header sizes
|
|
declare -A ML_DSA_HEADER_SIZES=(
|
|
[2]=8192
|
|
[3]=8192
|
|
[5]=12288
|
|
)
|
|
|
|
# Add to command options structure
|
|
declare -A COMMON_OPTS=(
|
|
[sign_pq_params]=""
|
|
[certchain_file]=""
|
|
[dummy_certchain]=""
|
|
)
|
|
|
|
# Add LCF_OPTS to command options structure
|
|
declare -A LCF_OPTS=(
|
|
[sign_algo]="$DEFAULT_SIGN_ALGO"
|
|
[use_elf_format]=""
|
|
)
|
|
|
|
# Add TARGET_OPTS to command options structure
|
|
declare -A TARGET_OPTS=(
|
|
[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
|
|
usage() {
|
|
echo "Usage: $0 [global-options] COMMAND [command-options] [COMMAND [command-options]]"
|
|
echo ""
|
|
echo "Global Options:"
|
|
echo " --hsm Use wolfHSM version"
|
|
echo " --elf Use ELF format for firmware images (affects target, macros, lcf, and sign commands)"
|
|
echo ""
|
|
echo "Commands and their options:"
|
|
echo " keygen"
|
|
echo " --sign-algo ALGO Signing algorithm (default: ecc256)"
|
|
echo " --localkeys Use local keys (only valid with --hsm)"
|
|
echo " --dummy-certchain Generate dummy certificate chain after key generation"
|
|
echo ""
|
|
echo " sign"
|
|
echo " --sign-algo ALGO Signing algorithm (inherits from keygen if not specified)"
|
|
echo " --hash-algo ALGO Hash algorithm (default: sha256)"
|
|
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 " target"
|
|
echo " No additional options"
|
|
echo ""
|
|
echo " clean"
|
|
echo " No additional options"
|
|
echo ""
|
|
echo " macros"
|
|
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 " --certchain FILE Certificate chain file to include in header"
|
|
echo " --dummy-certchain Use dummy certificate chain in header"
|
|
echo ""
|
|
echo " nvm"
|
|
echo " --dummy-certchain Use dummy certificate chain configuration"
|
|
echo ""
|
|
echo " lcf"
|
|
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 "Examples:"
|
|
echo " $0 keygen --sign-algo ecc256"
|
|
echo " $0 sign --hash-algo sha256 --debug"
|
|
echo " $0 keygen --sign-algo ecc256 sign --hash-algo sha256"
|
|
echo " $0 --hsm keygen --sign-algo ecc256 --localkeys sign --debug"
|
|
echo " $0 --elf target macros lcf sign"
|
|
echo " $0 clean"
|
|
echo " $0 macros"
|
|
echo " $0 nvm"
|
|
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
|
|
}
|
|
|
|
# Function to generate keys
|
|
do_keygen() {
|
|
local sign_algo="${KEYGEN_OPTS[sign_algo]:-$DEFAULT_SIGN_ALGO}"
|
|
|
|
echo "Generating keys with algorithm: $sign_algo"
|
|
|
|
(cd $WOLFBOOT_DIR && tools/keytools/keygen --"$sign_algo" -g $(basename $PRVKEY_DER) --exportpubkey \
|
|
${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
|
|
do_sign() {
|
|
local base_path="../../../IDE/AURIX"
|
|
local app_name="test-app${HSM:+-wolfHSM}"
|
|
local sign_algo="${SIGN_OPTS[sign_algo]:-${KEYGEN_OPTS[sign_algo]}}"
|
|
local pq_params="${COMMON_OPTS[sign_pq_params]}"
|
|
local header_size
|
|
local bin_path="$base_path/$app_name/TriCore ${SIGN_OPTS[build_type]} (GCC)/$app_name${SIGN_OPTS[file_ext]}"
|
|
|
|
# If signing an elf file, first preprocess it with squashelf
|
|
if [[ "${SIGN_OPTS[file_ext]}" == ".elf" ]]; then
|
|
local temp_file="${bin_path}.squashed"
|
|
echo "Preprocessing ELF file with $SQUASHELF"
|
|
"$SQUASHELF" -v --nosht -r "$PFLASH1_RANGE" "$bin_path" "$temp_file"
|
|
echo "Replacing original ELF with squashed version"
|
|
cp "$temp_file" "$bin_path"
|
|
rm "$temp_file"
|
|
fi
|
|
|
|
# Get header size for current algorithm
|
|
header_size=$(get_header_size "$sign_algo" "$pq_params" "$(get_effective_certchain_file)")
|
|
|
|
# Set IMAGE_HEADER_SIZE environment variable for sign tool
|
|
export IMAGE_HEADER_SIZE="$header_size"
|
|
|
|
echo "Signing binaries with $sign_algo and ${SIGN_OPTS[hash_algo]}"
|
|
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
|
|
../../keytools/sign --"$sign_algo" --"${SIGN_OPTS[hash_algo]}" $cert_chain_arg "$bin_path" "$PRVKEY_DER" 1
|
|
../../keytools/sign --"$sign_algo" --"${SIGN_OPTS[hash_algo]}" $cert_chain_arg "$bin_path" "$PRVKEY_DER" 2
|
|
}
|
|
|
|
# Function to generate target header
|
|
do_gen_target() {
|
|
local target_h_template="${TARGET_H}.in"
|
|
|
|
local wolfboot_sector_size=0x4000
|
|
|
|
# Select partition values based on whether --elf option was specified
|
|
local wolfboot_partition_size
|
|
local wolfboot_partition_boot_address
|
|
local wolfboot_partition_update_address
|
|
local wolfboot_partition_swap_address
|
|
|
|
if [[ -n "${TARGET_OPTS[use_elf_format]}" ]]; then
|
|
# These addresses and values must match those defined in the test-app
|
|
# linker file
|
|
wolfboot_partition_size=0xC0000
|
|
wolfboot_partition_boot_address=0xA047C000
|
|
wolfboot_partition_update_address=0xA053C000
|
|
wolfboot_partition_swap_address=0xA05FC000
|
|
else
|
|
# These addresses and values must match those defined in the test-app
|
|
# linker file
|
|
wolfboot_partition_size=0x17C000
|
|
wolfboot_partition_boot_address=0xA0300000
|
|
wolfboot_partition_update_address=0xA047C000
|
|
wolfboot_partition_swap_address=0xA05FC000
|
|
fi
|
|
|
|
local wolfboot_dts_boot_address=""
|
|
local wolfboot_dts_update_address=""
|
|
local wolfboot_load_address=""
|
|
local wolfboot_load_dts_address=""
|
|
|
|
echo "Generating target header file"
|
|
cat $target_h_template | \
|
|
sed -e "s/@WOLFBOOT_PARTITION_SIZE@/$wolfboot_partition_size/g" | \
|
|
sed -e "s/@WOLFBOOT_SECTOR_SIZE@/$wolfboot_sector_size/g" | \
|
|
sed -e "s/@WOLFBOOT_PARTITION_BOOT_ADDRESS@/$wolfboot_partition_boot_address/g" | \
|
|
sed -e "s/@WOLFBOOT_PARTITION_UPDATE_ADDRESS@/$wolfboot_partition_update_address/g" | \
|
|
sed -e "s/@WOLFBOOT_PARTITION_SWAP_ADDRESS@/$wolfboot_partition_swap_address/g" | \
|
|
sed -e "s/@WOLFBOOT_DTS_BOOT_ADDRESS@/$wolfboot_dts_boot_address/g" | \
|
|
sed -e "s/@WOLFBOOT_DTS_UPDATE_ADDRESS@/$wolfboot_dts_update_address/g" | \
|
|
sed -e "s/@WOLFBOOT_LOAD_ADDRESS@/$wolfboot_load_address/g" | \
|
|
sed -e "s/@WOLFBOOT_LOAD_DTS_ADDRESS@/$wolfboot_load_dts_address/g" \
|
|
> "$TARGET_H"
|
|
}
|
|
|
|
# Function to clean generated files
|
|
do_clean() {
|
|
echo "Cleaning generated files"
|
|
local macros_out="$WOLFBOOT_DIR/IDE/AURIX/wolfBoot-tc3xx${HSM:+-wolfHSM}/wolfBoot_macros.txt"
|
|
|
|
rm -f "$PRVKEY_DER"
|
|
rm -f "$PUBKEY_DER"
|
|
rm -f "$TARGET_H"
|
|
rm -f "$macros_out"
|
|
rm -f "$NVM_BIN"
|
|
rm -f "$NVM_HEX"
|
|
}
|
|
|
|
# Function to generate macros
|
|
do_gen_macros() {
|
|
# Set the macros paths dynamically based on HSM flag
|
|
local macros_in="$WOLFBOOT_DIR/IDE/AURIX/wolfBoot-tc3xx${HSM:+-wolfHSM}/wolfBoot_macros.in"
|
|
local macros_out="$WOLFBOOT_DIR/IDE/AURIX/wolfBoot-tc3xx${HSM:+-wolfHSM}/wolfBoot_macros.txt"
|
|
|
|
# Use macros options first, then fall back to sign/keygen options
|
|
local sign_algo="${MACROS_OPTS[sign_algo]:-${SIGN_OPTS[sign_algo]:-${KEYGEN_OPTS[sign_algo]:-$DEFAULT_SIGN_ALGO}}}"
|
|
local hash_algo="${MACROS_OPTS[hash_algo]:-${SIGN_OPTS[hash_algo]}}"
|
|
local pq_params="${COMMON_OPTS[sign_pq_params]}"
|
|
|
|
# Get header size using the new function
|
|
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_wolfhsm_pubkey_id=""
|
|
local image_signature_size=""
|
|
local ml_dsa_image_signature_size=""
|
|
local ml_dsa_level=""
|
|
local use_wolfboot_elf=""
|
|
local use_wolfboot_elf_flash_scattered=""
|
|
local use_wolfboot_cert_chain_verify=""
|
|
|
|
# Map algorithms to their macro names
|
|
local sign_macro="${SIGN_ALGO_MAP[${sign_algo,,}]:-}"
|
|
local hash_macro="${HASH_ALGO_MAP[${hash_algo,,}]:-}"
|
|
|
|
if [[ -z "$sign_macro" ]]; then
|
|
echo "Error: Invalid or missing signing algorithm"
|
|
exit 1
|
|
fi
|
|
if [[ -z "$hash_macro" ]]; then
|
|
echo "Error: Invalid or missing hash algorithm"
|
|
exit 1
|
|
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
|
|
if [[ "${sign_algo,,}" == "rsa4096" ]]; then
|
|
use_huge_stack="-DWOLFBOOT_HUGE_STACK"
|
|
fi
|
|
|
|
# Set HSM pubkey ID if using HSM without local keys
|
|
if [[ -n "$HSM" && -n "${KEYGEN_OPTS[nolocalkeys]}" ]]; then
|
|
use_wolfhsm_pubkey_id="-DWOLFBOOT_USE_WOLFHSM_PUBKEY_ID"
|
|
fi
|
|
|
|
# Set ELF format macros if --elf option was specified
|
|
if [[ -n "${MACROS_OPTS[use_elf_format]}" ]]; then
|
|
use_wolfboot_elf="-DWOLFBOOT_ELF"
|
|
use_wolfboot_elf_flash_scattered="-DWOLFBOOT_ELF_FLASH_SCATTER"
|
|
fi
|
|
|
|
# Quirk: set additional (redundant) macros for ML DSA based on pq_params
|
|
if [[ "${sign_algo,,}" == ml_dsa* ]]; then
|
|
local level="${pq_params:-2}" # Default to level 2 if not specified
|
|
case "$level" in
|
|
2)
|
|
image_signature_size="-DIMAGE_SIGNATURE_SIZE=2420"
|
|
ml_dsa_image_signature_size="-DML_DSA_IMAGE_SIGNATURE_SIZE=2420"
|
|
;;
|
|
3)
|
|
image_signature_size="-DIMAGE_SIGNATURE_SIZE=3300"
|
|
ml_dsa_image_signature_size="-DML_DSA_IMAGE_SIGNATURE_SIZE=3300"
|
|
;;
|
|
5)
|
|
image_signature_size="-DIMAGE_SIGNATURE_SIZE=5200"
|
|
ml_dsa_image_signature_size="-DML_DSA_IMAGE_SIGNATURE_SIZE=5200"
|
|
;;
|
|
esac
|
|
ml_dsa_level="-DML_DSA_LEVEL=$level"
|
|
fi
|
|
|
|
echo "Generating macros file with sign_algo=$sign_algo, hash_algo=$hash_algo"
|
|
sed -e "s/@HASH_ALGO@/${hash_macro#WOLFBOOT_HASH_}/g" \
|
|
-e "s/@SIGN_ALGO@/${sign_macro#WOLFBOOT_SIGN_}/g" \
|
|
-e "s/@IMAGE_HEADER_SIZE@/$image_header_size/g" \
|
|
-e "s/@IMAGE_SIGNATURE_SIZE@/$image_signature_size/g" \
|
|
-e "s/@ML_DSA_LEVEL@/$ml_dsa_level/g" \
|
|
-e "s/@ML_DSA_IMAGE_SIGNATURE_SIZE@/$ml_dsa_image_signature_size/g" \
|
|
-e "s/@WOLFBOOT_HUGE_STACK@/$use_huge_stack/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_FLASH_SCATTER@/$use_wolfboot_elf_flash_scattered/g" \
|
|
-e "s/@WOLFBOOT_CERT_CHAIN_VERIFY@/$use_wolfboot_cert_chain_verify/g" \
|
|
"$macros_in" > "$macros_out"
|
|
|
|
# Remove empty lines from the output file, as they cause compiler errors
|
|
sed -i '/^$/d' "$macros_out"
|
|
}
|
|
|
|
# Function to generate a wolfHSM NVM image
|
|
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 "Running: $WHNVMTOOL --image=$NVM_BIN --size=0x10000 --invert-erased-byte $nvm_config_file"
|
|
"$WHNVMTOOL" --image="$NVM_BIN" --size=0x10000 --invert-erased-byte "$nvm_config_file"
|
|
|
|
echo "Converting to Intel HEX format"
|
|
echo "Running: objcopy -I binary -O ihex --change-address 0xAFC00000 $NVM_BIN $NVM_HEX"
|
|
objcopy -I binary -O ihex --change-address 0xAFC00000 "$NVM_BIN" "$NVM_HEX"
|
|
}
|
|
|
|
# Function to generate LCF file
|
|
do_gen_lcf() {
|
|
# Check LCF_OPTS first, then fall back to SIGN_OPTS and KEYGEN_OPTS, default to DEFAULT_SIGN_ALGO
|
|
local sign_algo="${LCF_OPTS[sign_algo]:-${SIGN_OPTS[sign_algo]:-${KEYGEN_OPTS[sign_algo]:-$DEFAULT_SIGN_ALGO}}}"
|
|
local pq_params="${COMMON_OPTS[sign_pq_params]}"
|
|
local header_size
|
|
|
|
# Determine target directory based on HSM flag
|
|
local base_dir="$WOLFBOOT_DIR/IDE/AURIX"
|
|
local app_dir="test-app${HSM:+-wolfHSM}"
|
|
|
|
# Select template file based on whether --elf option was specified
|
|
local template_name
|
|
if [[ -n "${LCF_OPTS[use_elf_format]}" ]]; then
|
|
template_name="Lcf_Gnuc_Tricore_elf.lsl.in"
|
|
else
|
|
template_name="Lcf_Gnuc_Tricore_Tc.lsl.in"
|
|
fi
|
|
|
|
local lcf_template="$base_dir/$app_dir/$template_name"
|
|
local lcf_output="$base_dir/$app_dir/Lcf_Gnuc_Tricore_Tc.lsl"
|
|
|
|
header_size=$(get_header_size "$sign_algo" "$pq_params" "$(get_effective_certchain_file)")
|
|
|
|
echo "Generating LCF file with header_size=$header_size"
|
|
sed -e "s/@LCF_WOLFBOOT_HEADER_OFFSET@/$header_size/g" \
|
|
"$lcf_template" > "$lcf_output"
|
|
}
|
|
|
|
# Parse global options first
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--hsm)
|
|
HSM="1"
|
|
KEYGEN_OPTS[nolocalkeys]="1"
|
|
shift
|
|
;;
|
|
--elf)
|
|
ELF="1"
|
|
# Set ELF mode for relevant command options
|
|
SIGN_OPTS[file_ext]=".elf"
|
|
LCF_OPTS[use_elf_format]="1"
|
|
TARGET_OPTS[use_elf_format]="1"
|
|
MACROS_OPTS[use_elf_format]="1"
|
|
shift
|
|
;;
|
|
keygen|sign|target|clean|macros|nvm|lcf)
|
|
break
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
;;
|
|
*)
|
|
echo "Unknown global option: $1"
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Now parse commands and their options
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
keygen)
|
|
OPERATIONS+=("keygen")
|
|
CURRENT_OPTS="KEYGEN_OPTS"
|
|
shift
|
|
;;
|
|
sign)
|
|
OPERATIONS+=("sign")
|
|
CURRENT_OPTS="SIGN_OPTS"
|
|
shift
|
|
;;
|
|
target)
|
|
OPERATIONS+=("target")
|
|
CURRENT_OPTS="TARGET_OPTS"
|
|
shift
|
|
;;
|
|
clean)
|
|
OPERATIONS+=("clean")
|
|
CURRENT_OPTS=""
|
|
shift
|
|
;;
|
|
macros)
|
|
OPERATIONS+=("macros")
|
|
CURRENT_OPTS="MACROS_OPTS"
|
|
shift
|
|
;;
|
|
nvm)
|
|
OPERATIONS+=("nvm")
|
|
CURRENT_OPTS="NVM_OPTS"
|
|
shift
|
|
;;
|
|
lcf)
|
|
OPERATIONS+=("lcf")
|
|
CURRENT_OPTS="LCF_OPTS"
|
|
shift
|
|
;;
|
|
--sign-algo)
|
|
if [ -z "$CURRENT_OPTS" ]; then
|
|
echo "Error: --sign-algo must follow a command"
|
|
exit 1
|
|
fi
|
|
declare -n opts=$CURRENT_OPTS
|
|
# Update all command options that use sign_algo
|
|
KEYGEN_OPTS[sign_algo]="$2"
|
|
SIGN_OPTS[sign_algo]="$2"
|
|
MACROS_OPTS[sign_algo]="$2"
|
|
LCF_OPTS[sign_algo]="$2"
|
|
shift 2
|
|
;;
|
|
--hash-algo)
|
|
if [ -z "$CURRENT_OPTS" ]; then
|
|
echo "Error: --hash-algo must follow a command"
|
|
exit 1
|
|
fi
|
|
declare -n opts=$CURRENT_OPTS
|
|
opts[hash_algo]="$2"
|
|
shift 2
|
|
;;
|
|
--localkeys)
|
|
if [ "$CURRENT_OPTS" != "KEYGEN_OPTS" ]; then
|
|
echo "Error: --localkeys only valid for keygen command"
|
|
exit 1
|
|
fi
|
|
if [ -z "$HSM" ]; then
|
|
echo "Error: --localkeys can only be used with --hsm"
|
|
exit 1
|
|
fi
|
|
KEYGEN_OPTS[nolocalkeys]=""
|
|
shift
|
|
;;
|
|
--debug)
|
|
if [ "$CURRENT_OPTS" != "SIGN_OPTS" ]; then
|
|
echo "Error: --debug only valid for sign command"
|
|
exit 1
|
|
fi
|
|
SIGN_OPTS[build_type]="Debug"
|
|
shift
|
|
;;
|
|
--sign-pq-params)
|
|
if [[ -z "$CURRENT_OPTS" ]]; then
|
|
echo "Error: --sign-pq-params must follow a command"
|
|
exit 1
|
|
fi
|
|
|
|
# Validate the parameter value for ml_dsa
|
|
if [[ "${KEYGEN_OPTS[sign_algo]}" == "ml_dsa" || "${SIGN_OPTS[sign_algo]}" == "ml_dsa" ]]; then
|
|
if [[ ! "$2" =~ ^(2|3|5)$ ]]; then
|
|
echo "Error: --sign-pq-params must be 2, 3, or 5 for ML-DSA"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
COMMON_OPTS[sign_pq_params]="$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"
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Validate that we have at least one operation
|
|
if [ ${#OPERATIONS[@]} -eq 0 ]; then
|
|
echo "Error: Must specify at least one command (keygen, sign, or target)"
|
|
usage
|
|
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
|
|
for op in "${OPERATIONS[@]}"; do
|
|
case $op in
|
|
"keygen")
|
|
do_keygen
|
|
;;
|
|
"sign")
|
|
do_sign
|
|
;;
|
|
"target")
|
|
do_gen_target
|
|
;;
|
|
"clean")
|
|
do_clean
|
|
;;
|
|
"macros")
|
|
do_gen_macros
|
|
;;
|
|
"nvm")
|
|
do_gen_nvm
|
|
;;
|
|
"lcf")
|
|
do_gen_lcf
|
|
;;
|
|
esac
|
|
done
|