2026-01-08 2:22 AM - edited 2026-01-15 5:04 AM
Hi,
I am doing a feasibility study for SBSFU on an STM32H750, specifically firmware encryption and authenticity check. I am using the XCUBE expansion pack v2.8.0.
- Using prepareimage.py & modified keys.py along with default prebuild and postbuild.sh
- Using a single download + single active slot in external memory
- All protections are disabled
Modifications to default example:
- Adjusted default linker script to increase active + download slot size
- Modified keys.py to append 0xFF bytes to binary before encryption to meet 16 byte multiple requirement
Method altered: AES_CBC:encrypt
- generating new AES and ECDSA keys as mentioned in readme.txt
As mentioned in AN5056, section 4.2, I modified SECBOOT_CRYPTO_SCHEME to SECBOOT_ECCDSA_WITH_AES128_CBC_SHA256. I can see that prebuild.sh detects this change and adjusts accordingly.
Observations:
I have tested the firmware installation using ECDSA signature without encryption to get the following errors.
1. Error on first boot after flashing external memory with ST Link Debugger (Firmware.bin).
2. Error on first boot when updating firmware through Ymodem Loader (Firmware.sfb).
Additionally, when I attempt to use ECDSA signature with AES128 encryption, I keep getting the errors listed further down.
1. Error on first boot after flashing external memory with ST Link Debugger (Firmware.bin).
2. Error on first boot when updating firmware through Ymodem Loader (Firmware.sfb).
Error Source:
I see that if (MemoryCompare(fw_tag_output, fw_tag, SE_TAG_LEN) != SFU_SUCCESS){ in sfu_fwimg_common.c is where the error is being caught.
Potential Reason:
I believe I am not padding the binary to meet the 16 byte multiple requirement correctly. I do this by adding the following lines to keys.py @ line 61.
#check if buffer size is aligned on BS size
if (0 == (len(payload) % BS)):
# we do not need to pad
buffer=payload
encrypted = encryptor.encrypt(buffer)
else:
#raise Exception("AES CBC encryption requires the Firmware Image size to be a multiple of the AES block size (16 bytes)")
# Buffer size is not correct, pad with 0xFF to make it a multiple of 16 bytes
padding_length = BS - (len(payload) % BS)
print("Padding firmware with {} bytes (0xFF) to align to 16-byte boundary (Requirement for AES Encryption)".format(padding_length))
buffer = payload + (b'\xFF' * padding_length)
encrypted = encryptor.encrypt(buffer)
Does anyone have any advice on how I can diagnose this? I am really not sure how to go about this.
Thanks for your help!
Solved! Go to Solution.
2026-01-15 4:21 AM - edited 2026-01-15 5:05 AM
Hi,
16 byte alignment was the issue. I removed the changes I made in keys.py.
In SECBOOT_ECCDSA_WITH_AES128_CBC_SHA256, I placed code to pad any firmware binary with the required number of bytes to be 16 byte aligned. This is done before encryption. Please find it below.
Now, encryption works both when programmed into flash and when downloaded via Ymodem.
Bash Function:
# Function to ensure binary is 16-byte aligned (Required for AES encryption)
align_binary_16bytes() {
local binary_file=$1
local file_size=$(stat -c%s "$binary_file" 2>/dev/null)
local remainder=$((file_size % 16))
if [ $remainder -ne 0 ]; then
local padding_needed=$((16 - remainder))
echo "Firmware Binary file size: $file_size bytes (not aligned to 16 bytes)"
echo "Adding $padding_needed padding bytes"
# Add padding bytes (0xFF) to align to 16 bytes
dd if=/dev/zero bs=1 count=$padding_needed 2>/dev/null | tr '\0' '\377' >> "$binary_file"
local new_size=$(stat -c%s "$binary_file" 2>/dev/null)
echo "New binary file size: $new_size bytes (aligned to 16 bytes)"
else
echo "Firmware Binary file size: $file_size bytes (already 16-byte aligned)"
fi
}
Function Call:
Placed just before the encryption
# Make sure we have a Binary sub-folder in UserApp folder
if [ ! -e $userAppBinary ]; then
mkdir $userAppBinary
fi
# Ensure binary is 16-byte aligned <=====================================
align_binary_16bytes "$bin"
command=$cmd" "$prepareimage" enc -k "$oemkey" -i "$iv" "$bin" "$sfu
By doing the same in SECBOOT_ECCDSA_WITHOUT_ENCRYPT_SHA256, programming with a debugger and installing via Ymodem works for unencrypted firmware binaries.
With this solution, one doesn't have to compile a raw firmware binary to be 16 byte aligned. This script will pad it as required.
2026-01-15 4:21 AM - edited 2026-01-15 5:05 AM
Hi,
16 byte alignment was the issue. I removed the changes I made in keys.py.
In SECBOOT_ECCDSA_WITH_AES128_CBC_SHA256, I placed code to pad any firmware binary with the required number of bytes to be 16 byte aligned. This is done before encryption. Please find it below.
Now, encryption works both when programmed into flash and when downloaded via Ymodem.
Bash Function:
# Function to ensure binary is 16-byte aligned (Required for AES encryption)
align_binary_16bytes() {
local binary_file=$1
local file_size=$(stat -c%s "$binary_file" 2>/dev/null)
local remainder=$((file_size % 16))
if [ $remainder -ne 0 ]; then
local padding_needed=$((16 - remainder))
echo "Firmware Binary file size: $file_size bytes (not aligned to 16 bytes)"
echo "Adding $padding_needed padding bytes"
# Add padding bytes (0xFF) to align to 16 bytes
dd if=/dev/zero bs=1 count=$padding_needed 2>/dev/null | tr '\0' '\377' >> "$binary_file"
local new_size=$(stat -c%s "$binary_file" 2>/dev/null)
echo "New binary file size: $new_size bytes (aligned to 16 bytes)"
else
echo "Firmware Binary file size: $file_size bytes (already 16-byte aligned)"
fi
}
Function Call:
Placed just before the encryption
# Make sure we have a Binary sub-folder in UserApp folder
if [ ! -e $userAppBinary ]; then
mkdir $userAppBinary
fi
# Ensure binary is 16-byte aligned <=====================================
align_binary_16bytes "$bin"
command=$cmd" "$prepareimage" enc -k "$oemkey" -i "$iv" "$bin" "$sfu
By doing the same in SECBOOT_ECCDSA_WITHOUT_ENCRYPT_SHA256, programming with a debugger and installing via Ymodem works for unencrypted firmware binaries.
With this solution, one doesn't have to compile a raw firmware binary to be 16 byte aligned. This script will pad it as required.