c-its.dev · notes on cooperative-ITS

· 20 Jul 2026 · Updated · 6 min read

The CPOC Annex I naming trap

An L0 C-ITS testbed may skip the EU-TLM_<env> and <CPA-ID>_<RCA-NAME> naming conventions, and renaming later costs every consumer that pinned a HashedId8.


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 L1 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 a deployment that means to reach L1:

  • §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 include EU-TLM, EU-TLM_L0, EU-TLM_L1. A name like "Acme TLM" or "MyOrg TLM (testbed)" does not match §I.2.2.1. What that costs an L0 testbed is the subject of the section below.
  • §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, so you do not get to choose it. The one exception is the reserved value 0, which the protocol sets aside for L0 RCA certificates, so a testbed can form a structurally compliant 0_<RCA-NAME>_L0 without any assignment.
  • §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 and stops short of mandating it, 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

IEEE 1609.2, which TS 103 097 profiles, defines the HashedId8 of a certificate as the low-order eight bytes of the hash of its encoding, with the hash algorithm depending on the curve. The cert’s name is part of what gets hashed. Change the name, even by 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), running a second compliant hierarchy in parallel until the old pins expire, or accepting that you will never be CPOC-compliant. What no option gives you is the old HashedId8 under a new name: it is a structural identifier, with no logical meaning.

What “L0” buys you

L0 relaxes more than teams assume, and the protocol says so in one sentence. Section VIII.3.1: “No CP/SP audit and certification is needed for CAs/C-ITS stations to access the L0 Environment. No specific checks on permissions are performed by the CPOC when receiving L0 RCA Certificates, hence no full compliance to the CP/SP and CPOC protocol is needed.” The Common Criteria Protection Profiles are the L1/L2 burden. They live in their own annexes to the Security Policy and the Certificate Policy, unrelated to the naming Annex I this post is about, and neither mentions L0.

So an L0 testbed is not held to the naming convention by the protocol. What holds it is the future. The moment the plan includes L1, every certificate needs a compliant name, and the rename lands after consumers have pinned the old HashedId8. Many teams discover this 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:

  1. Read CPOC Protocol Release 3.2 Annex I before writing the cert factory. It runs to some fifty pages. It will save you the rename.
  2. Choose names that are at least structurally compliant. The reserved CPA-ID 0 is there for exactly this: 0_<your-pilot-name>_L0 is structurally compliant today, with nothing to request from anyone. The string can be argued about later; the structure cannot.
  3. 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 and the naming conventions are public. Shipping non-compliant names is defensible. Shipping them without having read the conventions first is what costs the rename.

The editor.



Comments

Anonymous OK · no email · 5 min edit window.