From 0966bba7d067a27c338dbaf0362e52cea2505f1f Mon Sep 17 00:00:00 2001 From: Andrew Bradford Date: Mon, 22 Jun 2026 15:36:16 -0400 Subject: [PATCH] zynqmp: Fix -verify header signature checking on non-FSBL ACs Each authentication certificate carries a boot header signature that must be signed by that AC's own SPK. Previously only the bootloader (FSBL) partition's AC was checked, so a bad boot header signature on the header-table AC or any non-FSBL partition AC would pass -verify undetected but fail to authenticate on real hardware. Extract the check into VerifyBootHeaderSignature() and call it for the header-table AC and for every authenticated partition (first block only for multi-block partitions), each verified against its own AC's SPK. Follow the seek/read sequence to use the nested style seen in neighbor functions and the partition loop. Fixup the trailing cleanup comment to "// Cleanup handled by unique_ptr", which is the standard phrasing used throughout. Signed-off-by: Andrew Bradford --- zynqmp/include/readimage-zynqmp.h | 1 + zynqmp/src/verifyimage-zynqmp.cpp | 73 +++++++++++++++++++------------ 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/zynqmp/include/readimage-zynqmp.h b/zynqmp/include/readimage-zynqmp.h index 966bf7f..06015e2 100755 --- a/zynqmp/include/readimage-zynqmp.h +++ b/zynqmp/include/readimage-zynqmp.h @@ -75,6 +75,7 @@ class ZynqMpReadImage : public ReadImage void VerifyAuthentication(bool); void VerifyHeaderTableSignature(); void VerifySPKSignature(AuthCertificate4096Structure * auth_cert); + void VerifyBootHeaderSignature(FILE * binFile, AuthCertificate4096Structure * auth_cert); void VerifyPartitionSignature(void); bool VerifySignature(bool nist, uint8_t * data, size_t dataLength, ACKey4096 * acKey, uint8_t * signature); diff --git a/zynqmp/src/verifyimage-zynqmp.cpp b/zynqmp/src/verifyimage-zynqmp.cpp index 361665a..8d58692 100755 --- a/zynqmp/src/verifyimage-zynqmp.cpp +++ b/zynqmp/src/verifyimage-zynqmp.cpp @@ -189,6 +189,9 @@ void ZynqMpReadImage::VerifyHeaderTableSignature() AuthCertificate4096Structure* auth_cert = (AuthCertificate4096Structure*)(aCs.front()); + /* Verifying Header AC Boot Header Signature */ + VerifyBootHeaderSignature(binFile, auth_cert); + /* Verifying Header SPK Signature */ VerifySPKSignature(auth_cert); @@ -269,6 +272,45 @@ void ZynqMpReadImage::VerifySPKSignature(AuthCertificate4096Structure* auth_cert } +/*******************************************************************************/ +void ZynqMpReadImage::VerifyBootHeaderSignature(FILE* binFile, AuthCertificate4096Structure* auth_cert) +{ + size_t result; + uint32_t bHLength = sizeof(ZynqMpBootHeaderStructure) + sizeof(RegisterInitTable); + if (bH->fsblAttributes & 0xC0) + { + bHLength += PUF_DATA_LENGTH; + } + + auto tempBHBuffer = std::make_unique(bHLength); + if (!(fseek(binFile, 0, SEEK_SET))) + { + result = fread(tempBHBuffer.get(), 1, bHLength, binFile); + if (result != bHLength) + { + LOG_ERROR("Error reading boot header while verifying "); + } + } + else + { + LOG_ERROR("Error seeking to boot header while verifying"); + } + + bool signatureVerified = VerifySignature(false, tempBHBuffer.get(), bHLength, &auth_cert->acSpk, (unsigned char*)(&auth_cert->acBhSignature)); + if (signatureVerified) + { + LOG_MSG(" BootHeader Signature Verified"); + } + else + { + LOG_MSG(" BootHeader Signature Verification Failed"); + authenticationVerified = false; + LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); + } + // Cleanup handled by unique_ptr +} + + /*******************************************************************************/ void ZynqMpReadImage::VerifyPartitionSignature(void) { @@ -293,35 +335,10 @@ void ZynqMpReadImage::VerifyPartitionSignature(void) bool checkLoadAddrInBhAndPht = ((*partitionHdr)->destinationExecAddress == bH->fsblExecAddress); bool isItBootloader = (checkLoadAddrInBhAndPht && (bH->sourceOffset != 0)); - - if (isItBootloader) - { - uint32_t bHLength = sizeof(ZynqMpBootHeaderStructure) + sizeof(RegisterInitTable); - if (bH->fsblAttributes & 0xC0) - { - bHLength += PUF_DATA_LENGTH; - } - auto tempBHBuffer = std::make_unique(bHLength); - size_t result = fread(tempBHBuffer.get(), 1, bHLength, binFile); - if (result != bHLength) - { - LOG_ERROR("Error reading boot header while verifying "); - } - - bool signatureVerified = VerifySignature(false, tempBHBuffer.get(), bHLength, &auth_cert->acSpk, (unsigned char*)(&auth_cert->acBhSignature)); - if (signatureVerified) - { - LOG_MSG(" BootHeader Signature Verified"); - } - else - { - LOG_MSG(" BootHeader Signature Verification Failed"); - authenticationVerified = false; - LOG_ERROR("Authentication verification failed on bootimage %s", binFilename.c_str()); - } - // tempBHBuffer is now unique_ptr, automatically deleted - } + /* Verifying each boot header with that AC's own secondary key. + For a multi-block partition only the first block's AC is checked. */ + VerifyBootHeaderSignature(binFile, auth_cert); /* Verifying Partition SPK Signature */ VerifySPKSignature(auth_cert);