· 20 Jul 2026 · 6 min read
The CPOC Annex I naming trap
What happens when an L0 C-ITS testbed quietly skips the EU-TLM_<env> and <CPA-ID>_<RCA-NAME> naming conventions, and why you can't fix it later without breaking every consumer.
There is a recurring pattern in V2X testbeds the editor would like to name explicitly: a project stands up its PKI hierarchy in three afternoons, the certs look right enough for the demo, the messages verify against each other, and the team moves on to the next problem. Eighteen months later somebody opens the CPOC Protocol Annex I and realises the cert names do not match anything the European trust list will accept.
The technical fix is half a day. The political fix is months.
What Annex I actually requires
The CPOC Protocol (Release 3.2, April 2026, the document hosted by JRC at cpoc.jrc.ec.europa.eu/documents/) is precise about how certificate identifiers must be formed at every level of the trust hierarchy. The relevant sections, for an L0 deployment:
- §I.2.2.1 — TLM CertificateID. The TLM cert name must start with the literal prefix
EU-TLM, optionally followed by_<TLM-ENVIRONMENT>, with_as the only allowed separator. Valid examples includeEU-TLM,EU-TLM_L0,EU-TLM_L1. A name like"Acme TLM"or"MyOrg TLM (testbed)"is non-compliant, full stop. - §I.3.2.2 — RCA CertificateID. Two components separated by
_:<CPA-ID>_<RCA-NAME>. Optional_<RCA-ENVIRONMENT>after that. The CPA-ID portion is assigned by the CPA — it is not a free choice. If you do not have a CPA-assigned ID, you cannot form a compliant RCA name. - §I.3.2.4 — EA/AA CertificateID. The recommended form mirrors the RCA convention, scoped to the subordinate CA. Annex I phrases it as a recommendation rather than mandatory, but stacks that strict-validate the trust list expect it.
None of this is technically hard. A sed over gen_hierarchy.py, a regeneration run, and you have compliant names. The trap is what regeneration costs.
The HashedId8 problem
ETSI TS 103 097 defines the HashedId8 of a certificate as the last eight bytes of the SHA-256 of its COER encoding. The cert’s name is part of what gets hashed. Change the name — even adding two characters — and the HashedId8 changes.
The HashedId8 is also how every consumer of your PKI references your trust anchors. Anyone who pulled your ECTL last month and pinned the Root CA HashedId8 in a config now has a stale pin. Their stack will refuse to verify your messages until they re-fetch and re-pin. If they have a release cadence of one image per quarter, you have created a quarter-long outage.
So the question becomes: are there consumers? In a testbed-of-one, no, and you regenerate freely. The moment an external partner starts polling your trust anchor — an OEM doing interop runs, another testbed federating, a research group running long-term measurements — you are in the position of either rolling over the entire trust chain with coordinated notice (months of work) or accepting that you will never be CPOC-compliant.
There is no third option. The HashedId8 is intentionally a structural identifier, not a logical one.
What “L0” buys you
A surprising amount of L0 confusion stems from conflating two things:
- Compliance with the CPOC Protocol document and Annex I conventions. L0 testbeds are expected to follow these conventions. The relaxation is not at the protocol level.
- Common Criteria Protection Profile certification of station and crypto-module hardware. This is the L1/L2 burden. Annex I to the Security Policy (the document
sp-annex-i-station-pps) and Annex I to the Certificate Policy (cp-annex-i-crypto-module-pps) list the approved profiles. L0 is explicitly out of scope for both annex documents.
So an L0 testbed dodges the hardware Common Criteria audit. It does not dodge the naming convention. Many teams discover this the hard way when they go from L0 demo to “we’d like to talk to a real RSU now”.
The defensible failure mode
If the choice is between non-compliant names and never operating the testbed in public, ship the testbed. That is the right call. The mistake is treating the naming as something that can be patched on the way to L1 — it cannot, because by then you have consumers and HashedId8 stability matters more than CPOC compliance.
The defensible failure mode is: ship with non-compliant names, document precisely why (a single paragraph in the testbed README is enough), and treat the rename as a coordinated event with a six-month notice window if and when CPOC accession actually becomes the goal. Pretending the rename is “trivial” because the diff is small is the part that goes wrong.
What to do on day zero
If you are spinning up a new C-ITS PKI hierarchy this week and there is any chance you will operate it for more than a year, three concrete recommendations:
- Read CPOC Protocol Release 3.2 Annex I before writing the cert factory. It is forty pages. It will save you the rename.
- Choose names that are at least structurally compliant. Even without a CPA-assigned ID,
LOCAL-TESTBED_<your-pilot-name>_L0is closer to the pattern thanAcme TLM. The string can be argued about later; the structure cannot. - Make HashedId8 visible in your operational logs from day zero. When the rename happens it is the single most important field to track across the cutover.
The CPOC Protocol document is open access. The naming conventions are public. There is no excuse besides not having read it before the first commit.
The editor.
Comments
Anonymous OK · no email · 5 min edit window.