Files
MicrOBU/microbu-esp32c5/external/vanetza-idf/docs/idf/evidence/independent-verifier-03/analysis.md
T
Ashin Walpola 0e9525162d Keep the colleague's microbu-esp32c5 tree in this repository
obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but
that tree was gitignored, so a clone of this repository could not build the
firmware it ships. It is now committed here as ordinary files in its own
folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP
bridge's signature verification (--trust) used on the bench. Nothing is
fetched from or pushed to the colleague's repository; this repository and
its remotes carry everything. The folder's own .gitignore keeps build output,
downloaded components and private key material out, as it did there; the
committed file set is identical to that repository's tracked files.

The ESP32-C5 is still flashed from obu-firmware/, which only takes
vanetza-idf from microbu-esp32c5/, so the two stay separate folders.
FLASHING.md says how to take a newer version of the colleague's tree (copy
it over the folder, rebuild, test, commit).
2026-09-23 17:46:40 +02:00

2.8 KiB

independent-verifier-03: the ESP32-C5 signs with credentials provisioned at run time

The board (COM11, test application examples/esp_idf_test, image of security-device-08) receives the twin chain of independent-verifier-02 as a credential bundle over its USB serial diagnostic channel (command 9, credentials.hpp format), resets into the secured profile, signs the CAM carriers, and c-its verifies the recorded frames against the twin root.

File Content
device.pcap three CAMs signed by the board with TWIN_AT (psid 638, 141, 36; region inherited)
device2.pcap the same with TWIN_AT2 (without psid 141)
host-bundle.pcap the host SUT provisioned from the same bundle file (vidf_sut --security-bundle), for comparison
c-its-*.jsonl c-its-pcap output per capture

The bundle files are not retained: they carry the tickets' private scalars (the twin chain's public certificates are in -02).

Commands

credential_bundle.py build --pool twin --root TWIN_RCA --aa TWIN_AA --at TWIN_AT  --out twin.vcr
credential_bundle.py build --pool twin --root TWIN_RCA --aa TWIN_AA --at TWIN_AT2 --out twin2.vcr
capture_pcap.py --port COM11 --bundle twin.vcr  --out device.pcap
capture_pcap.py --port COM11 --bundle twin2.vcr --out device2.pcap
capture_pcap.py --sut vidf_sut --bundle twin.vcr --out host-bundle.pcap
c-its-pcap device.pcap / device2.pcap / host-bundle.pcap   (ctl/root-TWIN_RCA.oer, ctl/aa-TWIN_AA.oer)

Result

Capture Signer Message signature Chain (root, AA, AT) signatures security_authorized
device.pcap ESP32-C5, PSA Crypto verifies (3/3) verify (3/3) false (psid 141 without SSP, c-its limitation as in -01)
device2.pcap ESP32-C5, PSA Crypto verifies (3/3) verify (3/3) true (3/3)
host-bundle.pcap host, OpenSSL verifies (3/3) verify (3/3) false (psid 141)

The generation times in device.pcap are the board's ITS clock as set by the capture (command 5) and the pcap timestamps the host's wall clock; c-its checks them against each other. The DENM carrier produces no frame because the twin tickets carry no psid 37 (the twin root's DENM range needs SSP version 2).

What this shows and what not

The run-time provisioning path exists end to end (bundle → diagnostic command → Credentials → apply() → security entity) and the board's signatures are accepted by an unrelated implementation. It does not show the project root: the twin has the real root's permissions and region but a throwaway key; the real chain is issued by the key holder with the same tools. Persistence across resets is the application's CredentialStore; the test application keeps the bundle in RAM and exercises the NVS store in test_credentials only.