Skip to content

Add SPDM measurements, challenge, heartbeat, key update, and cert chain validation#4

Open
aidangarske wants to merge 8 commits intomasterfrom
add-measurements-emu
Open

Add SPDM measurements, challenge, heartbeat, key update, and cert chain validation#4
aidangarske wants to merge 8 commits intomasterfrom
add-measurements-emu

Conversation

@aidangarske
Copy link
Owner

@aidangarske aidangarske commented Feb 17, 2026

Description

Scope

Implemented 6 core SPDM 1.2 protocol features in wolfSPDM and wolfTPM to bring the library from basic session establishment to production-ready device
attestation. All features are tested against the DMTF spdm-emu reference implementation.

Features Implemented

  1. Device Measurements (GET_MEASUREMENTS / MEASUREMENTS)
  • Build GET_MEASUREMENTS requests with optional signature request and nonce
  • Parse MEASUREMENTS responses with variable-length measurement record blocks (DMTF format)
  • Signature verification using L1/L2 transcript (VCA + request + response) with SPDM 1.2 signing prefix ("responder-measurements signing")
  • Public API: wolfSPDM_GetMeasurements(), wolfSPDM_GetMeasurementCount(), wolfSPDM_GetMeasurementBlock()
  • Conditional compilation via NO_WOLFSPDM_MEAS / NO_WOLFSPDM_MEAS_VERIFY
  1. Certificate Chain Validation
  • Load trusted root CA certificates (DER format) for chain validation
  • Hash-based root certificate verification against the SPDM cert chain header
  • Automatic responder public key extraction from leaf certificate
  • Backwards compatible: if no trusted CAs loaded, key extraction still works (with warning)
  • Public API: wolfSPDM_SetTrustedCAs()
  1. CHALLENGE / CHALLENGE_AUTH (Sessionless Attestation)
  • Sessionless device authentication per DSP0274 Section 10.8
  • Running M1/M2 hash accumulated during GET_VERSION through GET_CERTIFICATE
  • Signature verification using SPDM 1.2 signing prefix ("responder-challenge_auth signing")
  • Conditional compilation via NO_WOLFSPDM_CHALLENGE
  • Public API: wolfSPDM_Challenge()
  1. HEARTBEAT / HEARTBEAT_ACK (Session Keep-Alive)
  • Encrypted ping/pong over established session
  • Public API: wolfSPDM_Heartbeat()
  1. KEY_UPDATE / KEY_UPDATE_ACK (Session Key Rotation)
  • Supports both UPDATE_KEY (requester only) and UPDATE_ALL_KEYS (both directions)
  • Key re-derivation from saved app secrets using HKDF-Expand with "traffic upd" label per DSP0277
  • Correct key transition timing: derive new keys before decrypting ACK (responder encrypts ACK with new key)
  • VERIFY_NEW_KEY follow-up to confirm new keys work
  • Sequence number reset after key update
  • Public API: wolfSPDM_KeyUpdate()
  1. Application Data Transfer
  • Send/receive application data over encrypted SPDM sessions
  • Public API: wolfSPDM_SendData(), wolfSPDM_ReceiveData()
    Code Size Reduction (Phase 2) — 473 net lines removed
    Refactoring & consolidation:
  • Fixed cppcheck warning: narrowed blk variable scope in spdm_msg.c
  • Extracted wolfSPDM_BuildSimpleMsg() helper — consolidated 3 identical 4-byte message builders (GetDigests, EndSession, Heartbeat)
  • Added SPDM_CONNECT_STEP macro — compressed 7 connect steps in ConnectStandard and 3 in ConnectNuvoton
  • Moved 8 byte-order helpers from spdm_nuvoton.c to spdm_internal.h as static inline, added SPDM_Set32LE/SPDM_Get32LE — replaced 30+ inline byte-shift operations across
    spdm_msg.c and spdm_secured.c
  • Extracted wolfSPDM_Sha384Hash() helper — replaced 7 Init/Update/Final/Free SHA-384 boilerplate blocks across 3 files
  • Added wolfSPDM_BuildIV() inline helper — deduplicated 4 IV XOR construction blocks (Nuvoton 8-byte + MCTP 2-byte) in encrypt/decrypt
  • Wrapped 4 unused public API functions behind #ifndef WOLFSPDM_LEAN (EncryptMessage, DecryptMessage, SendData, ReceiveData)
  • Added SPDM_CHECK_ERROR_RSP macro and replaced GivePubKey/SetOnlyMode manual encrypt-send-decrypt with wolfSPDM_SecuredExchange() calls
  • Simplified tail error-return patterns in SecuredExchange and Finish
  • Replaced all 77 bulky 3-line /* ====... / section dividers with single-line / --- Section --- / style across all src/.c and header files
  • Added feature detection macros (WOLFSPDM_HAS_MEASUREMENTS, etc.) to spdm.h

CI addition:

  • Added spdm-emu-test.yml — full integration test workflow that builds wolfSSL, wolfSPDM, spdm-emu, and wolfTPM, then runs all 6 SPDM emulator tests (session,
    signed/unsigned measurements, challenge, heartbeat, key update)

Bug Fixes

  • IV XOR position (MCTP): Changed from rightmost bytes (10-11) to leftmost bytes (0-1) per DSP0277 ZeroExtend(SequenceNumber). Previously hidden because
    all messages used seq=0 (XOR with 0 is a no-op regardless of position).
  • HKDF label for KEY_UPDATE: Changed from "update" with version byte context to "traffic upd" with no context, matching DSP0277 bin_str9 format.

Testing

  • 17 new unit tests covering message building, parsing, signature verification, error handling, and accessor functions
  • 6 integration tests against spdm-emu (all passing):
    a. Session establishment
    b. Signed measurements (with signature verification)
    c. Unsigned measurements
    d. Challenge authentication
    e. Heartbeat
    f. Key update

wolfTPM Changes

  • Extended spdm_demo.c with --challenge, --heartbeat, and --key-update CLI flags
  • Updated spdm_test.sh to run all 6 emulator tests automatically
  • Updated documentation (SPDM.md, README.md)

Stats

  • wolfSPDM: +2829 / -1007 lines across 11 files
  • wolfTPM: +563 / -47 lines across 4 files
  • WOLFSPDM_CTX_STATIC_SIZE increased from 28KB to 32KB and 24KB without meas API's to accommodate new fields

…lidation

  Implement core SPDM 1.2 protocol features for production device attestation:
  - GET_MEASUREMENTS with signature verification (L1/L2 transcript, DSP0274)
  - CHALLENGE/CHALLENGE_AUTH sessionless attestation with signature verification
  - Certificate chain validation against trusted root CAs via wolfSPDM_SetTrustedCAs()
  - HEARTBEAT/HEARTBEAT_ACK session keep-alive
  - KEY_UPDATE/KEY_UPDATE_ACK session key rotation (DSP0277 traffic upd label)
  - Application data send/receive over encrypted sessions
  - Fix IV XOR position for MCTP to leftmost bytes per DSP0277

  All 6 spdm-emu integration tests pass. Bumps WOLFSPDM_CTX_STATIC_SIZE to 32KB.
@aidangarske aidangarske self-assigned this Feb 17, 2026
  - Extracted wolfSPDM_BuildSignedHash() — shared SPDM 1.2 signing prefix builder replacing 3 inline blocks (~40 lines each) in BuildFinish,
  VerifyMeasurementSig, VerifyChallengeAuthSig
  - Extracted wolfSPDM_VerifyEccSig() — shared raw-to-DER + ECC verify replacing 2 inline blocks
  - Reused wolfSPDM_FindLeafCert() in ExtractResponderPubKey (removed duplicated DER parsing loop)
  - Consolidated pub key extraction — ValidateCertChain now calls ExtractResponderPubKey instead of duplicating it
  - Applied SPDM_CHECK_BUILD_ARGS macro to 10 build functions
  - Applied SPDM_CHECK_PARSE_ARGS macro to 10 parse functions
  - Applied SPDM_CHECK_RESPONSE macro to 10 response code checks

  src/spdm_internal.h (+28 lines)
  - Added SPDM_CHECK_BUILD_ARGS, SPDM_CHECK_PARSE_ARGS, SPDM_CHECK_RESPONSE macros

  test/unit_test.c (-653 lines, +376 = -277 net)
  - Added ASSERT_SUCCESS, ASSERT_FAIL, ASSERT_EQ, ASSERT_NE test macros
  - Compressed all 34 test functions using these macros

  src/spdm_context.c (1 line) — const correctness fix
  src/spdm_kdf.c (3 lines) — moved variable declaration into scope

  Total: 7,255 → 6,639 lines (-616 lines, -8.5%)
  Refactoring & consolidation:
  - Fixed cppcheck warning: narrowed blk variable scope in spdm_msg.c
  - Extracted wolfSPDM_BuildSimpleMsg() helper — consolidated 3 identical 4-byte message builders (GetDigests, EndSession, Heartbeat)
  - Added SPDM_CONNECT_STEP macro — compressed 7 connect steps in ConnectStandard and 3 in ConnectNuvoton
  - Moved 8 byte-order helpers from spdm_nuvoton.c to spdm_internal.h as static inline, added SPDM_Set32LE/SPDM_Get32LE — replaced 30+ inline byte-shift operations across
  spdm_msg.c and spdm_secured.c
  - Extracted wolfSPDM_Sha384Hash() helper — replaced 7 Init/Update/Final/Free SHA-384 boilerplate blocks across 3 files
  - Added wolfSPDM_BuildIV() inline helper — deduplicated 4 IV XOR construction blocks (Nuvoton 8-byte + MCTP 2-byte) in encrypt/decrypt
  - Wrapped 4 unused public API functions behind #ifndef WOLFSPDM_LEAN (EncryptMessage, DecryptMessage, SendData, ReceiveData)
  - Added SPDM_CHECK_ERROR_RSP macro and replaced GivePubKey/SetOnlyMode manual encrypt-send-decrypt with wolfSPDM_SecuredExchange() calls
  - Simplified tail error-return patterns in SecuredExchange and Finish
  - Replaced all 77 bulky 3-line /* ====... */ section dividers with single-line /* --- Section --- */ style across all src/*.c and header files
  - Added feature detection macros (WOLFSPDM_HAS_MEASUREMENTS, etc.) to spdm.h

  CI addition:
  - Added spdm-emu-test.yml — full integration test workflow that builds wolfSSL, wolfSPDM, spdm-emu, and wolfTPM, then runs all 6 SPDM emulator tests (session,
  signed/unsigned measurements, challenge, heartbeat, key update)
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements 6 core SPDM 1.2 protocol features to transform wolfSPDM from basic session establishment into a production-ready device attestation library. The implementation is tested against the DMTF spdm-emu reference implementation with comprehensive unit and integration tests.

Changes:

  • Added device measurements (GET_MEASUREMENTS/MEASUREMENTS) with signature verification
  • Implemented certificate chain validation against trusted root CAs
  • Added sessionless authentication via CHALLENGE/CHALLENGE_AUTH
  • Implemented session keep-alive (HEARTBEAT) and key rotation (KEY_UPDATE)
  • Fixed IV XOR position bug (leftmost vs rightmost bytes per DSP0277)
  • Fixed HKDF label for KEY_UPDATE ("traffic upd" instead of "update")

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
wolfspdm/spdm_types.h Added measurement constants, key update operations, and SPDM_LABEL_UPDATE
wolfspdm/spdm.h Added public APIs for measurements, challenge, heartbeat, key update, cert validation; increased CTX size to 32KB
wolfspdm/spdm_error.h Added 6 new error codes for new features
wolfspdm/spdm_nuvoton.h Cleaned up comment formatting
src/spdm_internal.h Extended WOLFSPDM_CTX with measurement/challenge/key update state; added helper macros and byte-order functions
src/spdm_msg.c Implemented message building/parsing for measurements, challenge, heartbeat, key update; added signature verification helpers
src/spdm_session.c Implemented wolfSPDM_GetMeasurements, wolfSPDM_Challenge, wolfSPDM_Heartbeat, wolfSPDM_KeyUpdate; added M1/M2 hash accumulation
src/spdm_secured.c Fixed IV construction (leftmost bytes); added wolfSPDM_SendData/ReceiveData; refactored with byte-order helpers
src/spdm_transcript.c Added wolfSPDM_Sha384Hash helper for multi-buffer hashing
src/spdm_kdf.c Added wolfSPDM_DeriveUpdatedKeys for key rotation
src/spdm_crypto.c Comment formatting cleanup
src/spdm_context.c Added wolfSPDM_SetTrustedCAs and measurement accessor functions; added cleanup for responderPubKey and m1m2Hash
src/spdm_nuvoton.c Moved byte-order helpers to spdm_internal.h; refactored with SPDM_CHECK_ERROR_RSP macro
test/unit_test.c Added 17 new unit tests covering all new features
README.md Updated with new API documentation and emulator test instructions
.github/workflows/spdm-emu-test.yml Added CI/CD workflow for automated emulator testing

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…s (GCC 11/12/13, Clang 14/15/17) with -Wall -Wextra -Werror, runs unit tests. Uses concurrency to cancel

   stale runs. wolfSSL is cached (shared across all matrix jobs).

  .github/workflows/README.md — One-line summary table of all 8 workflows so you can see at a glance what each file does without opening them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant