Keep vanetza-idf in obu-firmware, so a plain clone builds the firmware
obu-firmware builds against the vanetza-idf C-ITS library, which until now came from the colleague's microbu-esp32c5 tree beside the repository and was not tracked here, so a clone of this repository could not build the firmware it ships. The library alone is now part of obu-firmware, as obu-firmware/external/vanetza-idf: their external/vanetza-idf at commit cf4b99f, unchanged (9775 files; see its PROVENANCE.md). CMake takes it from there by default; -DVANETZA_IDF_DIR still points the build elsewhere. The rest of the colleague's tree (their own VAM firmware, PKI tooling, station-link Python tools, the V2X2MAP bridge) stays out of this repository and gitignored; nothing is pushed to their repository. NOTES.md, docs/06, TODO.md and the pcap verifier's usage line point at the new location.
This commit is contained in:
+84
@@ -0,0 +1,84 @@
|
||||
# independent-verifier-01: signed CAM/DENM checked by c-its
|
||||
|
||||
An independent implementation (c-its, Rust, https://github.com/TheEnbyperor/c-its,
|
||||
commit e3bb3b82480d6df4237e2a8c35ea0dd7eade25b4 of 2026-09-07; rasn/rasn-its
|
||||
codecs, RustCrypto p256) verifies what the host SUT signs with a lab credential
|
||||
chain issued by `vidf_issue`. Nothing of the verification is ours: c-its
|
||||
decodes the GeoNetworking and TS 103 097 structures with its own ASN.1
|
||||
modules, checks the message signature, every certificate signature up to the
|
||||
root it is given, the chain lengths, the end-entity permissions against the
|
||||
issuers' `certIssuePermissions` and finally the CAM/DENM content against the
|
||||
ticket's SSP (`security_authorized`).
|
||||
|
||||
## Material (public parts only)
|
||||
|
||||
| File | Content |
|
||||
| --- | --- |
|
||||
| `LAB_RCA.oer` | self-signed root, `vidf_issue root` from a throwaway P-256 key (`openssl ecparam -genkey`), CPOC-shaped `certIssuePermissions` (minChainLength 2, eeType app+enrol; second group psid 623 013E/FFC1) |
|
||||
| `LAB_AA.oer` | AA under the root, appPermissions psid 623 ssp 0130 |
|
||||
| `LAB_AT.oer` | standard ticket: psid 36 (01FFFC), 37 (01FFFFFF), 141 (no SSP), 638 (01) |
|
||||
| `LAB_AT_NOMGMT.oer` | the same without psid 141 |
|
||||
| `sut-standard.pcap`, `sut-nomgmt.pcap` | three CAM carriers (certificate, digest, certificate) and one DENM carrier (GBC) each, recorded with `tools/capture_pcap.py` |
|
||||
| `c-its-standard.jsonl`, `c-its-nomgmt.jsonl` | c-its-pcap output, one JSON object per frame |
|
||||
|
||||
Private keys (`*.vkey`, the PEM) are not part of the evidence. The lab root is
|
||||
not the project's root certificate; the procedure is the one the project root
|
||||
would go through (`vidf_issue root --key <encrypted PEM>`, pass phrase prompted
|
||||
by OpenSSL, never on the command line).
|
||||
|
||||
## Commands
|
||||
|
||||
```
|
||||
vidf_issue root --key lab-root.pem --name "vanetza-idf lab root" --id LAB_RCA --out chain
|
||||
vidf_issue authority --issuer chain/LAB_RCA.oer --issuer-key lab-root.pem --name "vanetza-idf lab AA" --id LAB_AA --out chain
|
||||
vidf_issue ticket --issuer chain/LAB_AA.oer --issuer-key chain/LAB_AA.vkey --id LAB_AT \
|
||||
--permission 36:01FFFC --permission 37:01FFFFFF --permission 141 --permission 638:01 --out chain
|
||||
vidf_issue ticket ... --id LAB_AT_NOMGMT --permission 36:01FFFC --permission 37:01FFFFFF --permission 638:01 --out chain
|
||||
python tools/capture_pcap.py --sut vidf_sut --pool chain --root LAB_RCA --aa LAB_AA --at LAB_AT --out sut-standard.pcap
|
||||
python tools/capture_pcap.py --sut vidf_sut --pool chain --root LAB_RCA --aa LAB_AA --at LAB_AT_NOMGMT --out sut-nomgmt.pcap
|
||||
mkdir ctl && cp chain/LAB_RCA.oer ctl/root-LAB_RCA.oer && cp chain/LAB_AA.oer ctl/aa-LAB_AA.oer
|
||||
RUST_LOG=info c-its-pcap sut-standard.pcap > c-its-standard.jsonl
|
||||
RUST_LOG=info c-its-pcap sut-nomgmt.pcap > c-its-nomgmt.jsonl
|
||||
```
|
||||
|
||||
c-its was built on Windows with `cargo build --release --features build-binary
|
||||
--bin c-its-pcap` (cargo 1.98.1). Its `ieee80211` dependency enables `defmt`
|
||||
by default, which needs an embedded logger and does not link on a host; the
|
||||
local checkout sets `ieee80211 = { version = "0.5.9", default-features = false,
|
||||
features = ["crypto"] }` (a build change, no functional change).
|
||||
|
||||
## Result
|
||||
|
||||
| Capture | Frames | Message signature | Certificate signatures (root, AA, AT) | Chain lengths / eeType | `ee_permissions_valid` | `validated_chain` | `security_authorized` |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `sut-nomgmt.pcap` | 3 CAM + 1 DENM | verifies (4/4) | verify (4/4) | root [2,2] app+enrol, AA [1,1] app | true | chain 0 (root → AA → AT) | **true** for the CAMs and the DENM |
|
||||
| `sut-standard.pcap` | 3 CAM + 1 DENM | verifies (4/4) | verify (4/4) | as above | false | none | false |
|
||||
|
||||
The digest-signed CAM (second frame) is resolved by c-its from the certificate
|
||||
it saw in the first frame; the DENM carries the certificate (TS 103 097 clause
|
||||
7.1.2) and the generationLocation.
|
||||
|
||||
The difference between the two captures is psid 141 (GN-MGMT) alone: the
|
||||
standard ticket lists it without an SSP, which IEEE Std 1609.2 permits and the
|
||||
ETSI test-suite tickets do as well (`CERT_IUT_A_AT`: `<ssp aid="GN-MGMT">`
|
||||
empty), and which is consistent with an issuer range `all`. c-its maps an
|
||||
appPermissions entry without SSP to `AppPermission::Unsupported`
|
||||
(`src/security/perms.rs`, `_ => Self::Unsupported`), and
|
||||
`CertSubjectAuthorization::authorizes` returns false for every unsupported
|
||||
entry (`src/security/certs.rs`), so c-its cannot validate the permissions of
|
||||
any ticket that carries GN-MGMT that way. The second capture removes the
|
||||
entry to show that everything else c-its checks passes.
|
||||
|
||||
## What this found on our side
|
||||
|
||||
The first attempt (not retained) used the previous lab profile: root and AA
|
||||
with the default chain length (1) and a bitmap range `00/FF` for GN-MGMT, the
|
||||
AA with the end-entity SSP 01C0 for psid 623. c-its verified all signatures
|
||||
but reported `ee_permissions_valid: false` because a root whose
|
||||
`certIssuePermissions` permit a chain of length 1 does not authorise a ticket
|
||||
two certificates below it (IEEE Std 1609.2 6.4.28). The lab issuer and the
|
||||
test pool now follow the EU CCMS CPOC Protocol Release 3.0 root profile
|
||||
(minChainLength 2, eeType app+enrol, the two psid 623 groups) and TS 102 941
|
||||
V2.2.1 Table B.6 for the CA-side SSPs; the library's own verifier gained the
|
||||
chain consistency checks it lacked (`docs/idf/validation.md`, "Chain
|
||||
consistency").
|
||||
Reference in New Issue
Block a user