Castell · SkyV2X

ECTL · trust list

The European Certificate Trust List
for C-ITS

The European Certificate Trust List enumerates every Root CA that participating ITS stations are willing to accept. Castell publishes its testbed ECTL under ETSI TS 102 941: signed by the TLM, sequence-numbered, and exposed as a single download.

ECTL signing and distribution flow on Castell TLM trust list manager B52CD033B4BA4AE4 ECTL signed by TLM · COER payload: ToBeSignedTlmCtl Root CA #1 D5CC48BA56F87FCA Root CA #N (one entry per root) ecdsaBrainpoolP384r1Signature Vehicle v2x stack pins TLM · verifies sig signs GET /getectl application/octet-stream · ~730 bytes · sequence-numbered
How the TLM signs the ECTL and how a station retrieves and verifies it.

What an ECTL is

The ECTL (European Certificate Trust List) is a signed file listing the certificates of the Root CAs the trust framework recognises. It lets a vehicle check whether a certificate chain roots in a Root CA the policy authority has approved.

In production C-ITS, the Trust List Manager (TLM) signs the ECTL and the CPOC (the C-ITS Point of Contact, run by the JRC) publishes it. In Castell, its own TLM keypair plays that role. The semantics are identical; only the policy provenance differs.

ETSI TS 102 941 defines the trust model. ETSI TS 103 097 defines the wire format of the signed message that carries it. IEEE 1609.2 sits underneath both for the cryptographic primitives.

How Castell serves the ECTL

Castell serves the ECTL at GET /getectl. The response is the COER-encoded ToBeSignedTlmCtl wrapped in a signed message, returned as application/octet-stream.

curl -sS https://pki.skyv2x.com/getectl -o ectl.coer
file ectl.coer
# ectl.coer: data
wc -c ectl.coer
# ~730 bytes (current size — grows with each Root CA in the list)

The endpoint also exposes a JRC-profile alias at GET /getectl/{hashedId8} for clients that follow the EU CPOC URL convention. Both return the same bytes; only the response headers differ slightly (the JRC alias adds X-Alias-Of: /getectl).

Every change to the Root CA inventory publishes a new edition: a full ECTL and its delta share the next sequence number, and the delta lists what changed since the previous full list (add and delete commands). GET /getdeltaectl/{hashedId8} returns the latest delta, GET /getdeltaectl/{hashedId8}/{seq} the delta of a given sequence; earlier editions stay available while the list is valid. Stacks that cache the ECTL compare sequence numbers between fetches and re-validate the chain if it advanced.

What is inside

Per §6.3.4, each RootCaEntry in the signed payload (ToBeSignedTlmCtl) carries two things:

Access points, the URLs at which subordinate CAs publish their metadata, are not in the ECTL. They live in the EaEntry, AaEntry and DcEntry records of each Root CA's own CTL.

The outer signature is an EcdsaP384Signature produced by the TLM private key: the TLM signs with Brainpool P-384 and SHA-384, the only algorithm the C-ITS Certificate Policy makes mandatory for it, so its HashedId8 is the last 8 bytes of the SHA-384 of the certificate. Verifying it requires pinning the TLM certificate, which Castell publishes separately at GET /tlm.

CTL, CRL and delta lists

The CTL and the CRL do opposite jobs, and TS 102 941 defines both. The CTL is an allow-list; the CRL is a deny-list.

The ECTL is the CTL the TLM issues, and it lists the Root CAs the network accepts (§6.3.1). Each Root CA in turn issues its own CTL, listing the subordinate EAs, AAs and distribution centres beneath it, plus a Certificate Revocation List (CRL) that names the HashedId8 of any CA certificate no longer trusted (§6.3.3). While validating a certificate path, a station loads trust anchors from the CTL and rejects the revoked identifiers in the CRL. Revocation is permanent; a revoked certificate is never reinstated.

A trust list comes in one of two shapes that share the same CtlFormat (§6.3.4). A full CTL (isFullCtl = TRUE) carries every entry; a delta CTL (isFullCtl = FALSE) carries only what changed since the previous full list, and shares its ctlSequence. That sequence climbs by one and is clipped at 255, so the TLM re-keys its certificate before signing a 256th list, and the count resets with the new certificate.

Trust anchors themselves rotate through link certificates (§6.4). When the TLM or a Root CA re-keys, it issues a link certificate that binds the old key to the new one, so stations can follow the change without re-provisioning out of band. The entries a CTL can carry (RootCaEntry, EaEntry, AaEntry, DcEntry, TlmEntry) live in the EtsiTs102941TrustLists module, and the CRL structure comes from IEEE 1609.2.

Consuming it from a V2X stack

The typical integration sequence is:

  1. Pin the TLM cert once, out of band, by fetching /tlm and verifying its fingerprint matches the value in /capabilities.trust_anchors.tlm.
  2. Fetch /getectl. Verify its signature against the pinned TLM cert.
  3. Parse the payload. Extract each Root CA entry's certificate and HashedId8.
  4. Use the extracted Root CAs to validate any subsequent EC, AT or ITS station certificate chain you receive.
  5. Cache the sequence number. Re-fetch periodically: the ECTL's nextUpdate field bounds its validity; Castell does not throttle the endpoint.

ECTL status

The production ECTL is maintained by the CPOC (JRC) and re-issued whenever the set of trusted Root CAs changes, each edition carrying a new ctlSequence. The authoritative, always-current version and its change logbook live at the CPOC. Castell's testbed ECTL carries its own independent sequence. Fetch /getectl and read the ctlSequence, or query /capabilities for the current trust material.

Caveat: this is the testbed ECTL

The ECTL Castell serves contains Castell's own testbed Root CAs, not the real EU CPOC trust list. Real C-ITS deployments must use the CPOC-issued ECTL. Castell's is for development, conformance testing and decoder work. It lets you exercise the full TS 102 941 trust-validation path against a file you control, without CPOC enrolment.

Related material