The FitSec library provides a high-performance security engine for processing messages and certificates within Intelligent Transport Systems (ITS) communications.
The library implements the following standards:
- IEEE 1609.2-2022 - Main specification for ITS security message headers and certificate formats.
- ETSI TS 103 097 v2.1.1 - The ETSI profile for IEEE 1609.2.
- ETSI TS 102 941 v2.2.1 - PKI and trust mechanisms.
- ETSI TS 103 601 v2.2.1 - ETSI ITS security extensions.
- ETSI TS 103 759 v2.1.1 - Misbehaviour reporting protocol (ongoing).
Basic Features:
- Efficiency: Optimized for minimal memory and CPU consumption.
- Extensibility: Plugin interface for software cryptographic libraries and Hardware Security Modules (HSMs).
- Flexibility: Supports both synchronous and asynchronous message processing.
Secured Message Handling:
- Encoding and decoding of ITS secured messages (including extensions) per ETSI TS 103 097 v2.1.1.
- Signature generation and verification.
- Message validation based on signing certificate restrictions.
- Peer-to-peer certificate distribution.
PKI features:
- Support for multiple Root, Enrolment (EA), and Authorization (AA) Certificate Authorities.
- Independent Enrolment Credential (EC) and Authorization Ticket (AT) certificate pools for each ITS-S application.
- Creation and handling of certificate requests (EC or AT).
- Automatic AT certificate selection for outgoing messages.
- Support for Certificate Revocation Lists (CRL) and Trust Lists (CTL/ECTL).
- Explicit and implicit certificate support.
- Peer-to-peer CRL/CTL requests.
- Certificate requests repetition.
The library is compatible with any communication protocol, including GeoNetworking (ETSI EN 302 636-4-1). It is written in standard C for cross-platform compatibility and has been tested on:
- Linux: gcc (x86, ARM)
- Windows: MinGW32, Cygwin, Visual C++ 14 (x86)
Note: Binaries provided for testing may contain feature restrictions. Please contact the author for full versions. Simulator: Try the library using the ITS message simulator: fsmsggen
Dependencies are managed via git submodules:
- cshared - An open-source utility library.
- fscrypt - A wrapper library for cryptographic engines. Currently supported:
- OpenSSL.
- AutoTalk Craton2 HSM engine (experimental).
- Custom engines can be implemented via the plugin API. See fscrypt README.
The primary API is defined in fitsec.h header file.
Initialize the engine instance using FitSec_New, which requires a FitSecConfig structure.
Step 1. First of all, Initialize the engine instance using using the FitSec_New call.
This function takes a configuration structure of type FitSecConfig as a parameter.
The FitSecConfig contains the following configuration fields:
version- A protocol version. Set it to3according to IEEE 1609.2 and ETSI TS 103 097flags- Configuration flags bitmap. See theFitSecEngineFlagsdata type for possible bit fields.appProfiles- An array ofFitSecAppProfilestructures describing ITS applications:aid- ITS application IDpayloadType- Message payload type for outgoing messages.fields- Bitmap of mandatory outgoing message elements. SeeFitSecAppProfileFlagsfor details.certPeriod- Delay (ms) between certificate inclusions. Special values are:-1- never send certificates, use digests in all messages0- send certificates within each outgoing message (default for DENM, SPAT, MAP, etc.)- some positive value defines a maximum delay between two messages containing certificates. For example set to 1000 to send certificate each second (default for RSU CAM)
certChangePeriod- Maximum lifetime (s) for an AT certificate before rotating to a new one from the pool.
encKeyStorageDurationDuration in seconds to keep previously used symmetric key for decrypting incomming messages (only for PKI messages for now). -storeTrustInformationCall user call-back to store received CA certificates, CRLs and CTLs.
Crypto engines:
The library provides a flexible way for using different crypto engines for different purposes. Crypto engines are referenced by name.
Two crypto engines are supported now: openssl and atlk (AutoTalk Craton 2 HSM library).
Please have a look on cryptographic plugin definition in fitsec_crypt_plugin.h and fitsec_hash_plugin.h.
hashEnginecrypto engine for hash functions. Currently "openssl" and "atlk" are supported, set to NULL for autoselectsignEnginecrypto engine for signing: "openssl", "atlk", NULL by defaultverifyEnginecrypto engine for sugnature verification: "openssl", "atlk", NULL by defaultencryptEnginecrypto engine for EC encrypting engine: "openssl", "atlk", NULL by defaultdecryptEnginecrypto engine for EC decryption: "openssl", "atlk", NULL by defaultsymmEncryptEnginecrypto engine for symmetric encryption: "openssl", "atlk", NULL by defaultsymmDecryptEnginecrypto engine for symmetric decryption: "openssl", "atlk", NULL by defaultmacEnginecrypto engine for MAC calculatoin: "openssl", "atlk", NULL by defaultrandomEnginecrypto engine for random function: "openssl", "atlk", NULL by default
Callbacks:
The library has two work modes: synchronous and asynchronous. In asynchronous mode the library interacts with the upper layer using the set of callback functions. The following callbacks are defined in the configuration structure:
cbOnSigneduser callback function to be called when the outgoing message is signed and ready to be sent to the networkcbOnValidateduser callback function to be called when the incoming message is validatedcbOnEncrypteduser callback function to be called when the outgoing message is encryptedcbOnDecrypteduser callback function to be called when the incoming message is decryptedcbOnEventuser callback function to be called when some event is occurred (@see FSEventId)cbOnEventUseruser pointer to be passed to all callback functions
Certificate pool parameters:
maxReceivedPoolSizeMaximum number of received AT certificates stored.maxReceivedLifeTimeMaximum life time of received AT certificates.purgePeriodperiod in seconds when received certificate pools must be purged. Set to 0 to never purge the pool. In this case two previous parameters doesn't make any sense.ctlCheckPeriodInterval in seconds between new CTL checks. Typically shall be at least 24h.crlCheckPeriodInterval in seconds between new CRL checks. Typically shall be at least 24h.
This configuration structure can be initialized using the FitSecConfig_InitDefault and modified according to user's needs. Please have a look at the fitsec.h for the description of configuration fields.
Step 2. Install all necessary certificates using function FitSec_InstallCertificate.
Any types of certificates can be installed: Root, TLM, EA, EC, AA, AT or any other custom certificate types in any order.
Authorization tickets shall be followed by the correspondent private keys or HSM key identifiers.
Important: all self-signed (Root) certificates installed by this function will be verified against itself and considered as trusted by default.
CTL/ECTL/CRL can also be installed. See CTL/CRL support chapter for information.
Step 3. Now the engine is ready to work. Messages processing can start.
Processing occurs in two stages to optimize memory by operating directly within the buffer provided by the facility layer:
- preparation of the message header
- signing the message
To optimize the memory manipulation efforts, all message operations performed directly within the message buffer, provided by the facility layer. This buffer with encoded message, can be passed later to the transport layer. The buffer shall contain enough space for all security headers, certificate(s) and the message payload.
According to the GeoNetworking specification, Security Header takes place between Basic GN Header and Common GN Header elements in GeoNetworking message structure.
Geonetworking layer shall execute the following steps to encode a secured message:
- allocate (or prepare) a memory buffer.
- prepare Basic GN Header strucutre.
- call
FitSec_PrepareSignedMessageto generate Security header - populate the payload starting by Common GN Header, following by BTP and facility data.
- update the
payloadSizefield in message information structure.(Note: Please don't spend too much time in this stage to avoid CAM signing rules violation.)
- call
FitSec_FinalizeMessageorFitSec_FinalizeSignedMessageAsyncto sign the message.
Please see the fitsec.h for function descriptions.
Call FitSec_PrepareSignedMessage to create the Security Header element and store it in the outgoing buffer.
This function must be called with the message information structure, containing following information:
messageandmessageSizecontaining the outgoing buffer address and sizepayloadTypecontaining the type of the security envelop: signed, encrypted, etc. (optional, set toFS_PAYLOAD_AUTOby default).positioncontaining current geographic position if necessary. (optional, not needed for CAM)generationTimecontaining the timestamp when the last GPS fix has been reached.signcontaining information about signing procedure. Following fields shall be set:signerTypeSet toFS_SI_AUTOto set the signer type automatically, according to the ITS application ID. Other values are:FS_SI_CERTIFICATEorFS_SI_DIGEST- use certificate or certificate digest to sign the message.
Certificate can be provided insign.certfield or can be selected automatically according to provided time, position and ITS application ID.FS_SI_SELF- sign message using the private key provided insign.privfield.
This field can be NULL during the preparation stage but should be set to a real value on the final stage. The signing algorithm shell be specified insign.algfield.
sspcontaining application ID and SSP bits, describing the content of the message.
The ITS AID list can be found on ISO TS17419 V2016-02-09: "ITS-AID_AssignedNumbers". SSP bits values described in ITS service standards.
The function creates the ITS Security Header in the provided buffer and fill the message information structure with:
payloadcontaining the pointer inside the memory buffer where the payload data shall be copied.payloadSizecontaining the maximum size of the payload buffer.signcontaining some information about signing procedure:signerTypeis set to the actual type of signer:FS_SI_CERTIFICATE,FS_SI_DIGESTorFS_SI_SELFcertis set to the certificate to be used to sign message ifsignerTypeis set to theFS_SI_CERTIFICATEorFS_SI_DIGEST. This value can be changed before or during the final stage. Set to NULL for automatic selection.
The data in the message information structure will be used on the next stage, so please keep it unchanged, excepting the payload size field.
The function returns the amount of bytes occupied in the output buffer by Secured Header or 0 if error occured. The error ID is provided in the message information structure.
Please see the fitsec.h for function descriptions.
The GeoNetworking layer than needs to create the Common Header and, optionally the Extended Header elements, and add the facility layer payload into the outgoing buffer.
The total length of all these elements shall be provided to the library using payloadSize field in the message information structure.
When the payload buffer is ready, the message shall be actually signed or encrypted, depending of it's payload type.
The user code must call FitSec_FinalizeMessage to perform these tasks. For asynchronous procedure the FitSec_FinalizeSignedMessageAsync can be used.
This function takes same parameters as the FitSec_PrepareMessage.
The function returns the full size of secured packet or 0 if error occured. The error ID is provided in the message information structure.
The library supports encryption based on IEEE 1609.2 specifications using algorithms defined in ETSI TS 103 097. The procedure of message encryption is similar to signing:
- preparation of the buffer using
FitSec_PrepareEncryptedMessage - adding one or more recipients.
- applying the payload
- actual encrypting using
FitSec_FinalizeEncryptedMessage
FitSec_PrepareEncryptedMessage function shall be called to initialize the outgoing buffer with the message header.
The function should be called with the message information structure, containing at least:
messageandmessageSizewith the outgoing buffer address and sizepayloadTypecontaining the type of the security envelop: signed, encrypted, etc. (optional, set toFS_PAYLOAD_AUTOby default).generationTimecontaining the timestamp, when the last GPS fix has been reached. This field is needed to select proper certificates and to process cached values.
The encrypted message can be addressed for up to 8 recipients. For the moment the library supports two types of encryption recipients: certificate or pre-shared keys (PSK). Not more than 1 PSK recipient is allowed.
FitSec_AddEncryptedMessageCertificateRecipient function add certificate into recipients list. This function shall be called with message information structure and the certificate id.
FitSec_AddEncryptedMessagePSKRecipient add a PSK recipient into recipients list. The actual symmetric key can be provided in the symkey parameter or it can be referenced using digest if the key was used recently and is expected in the keys cache. The encKeyStorageDuration configuration parameter defines an encryption cache lifetime interval.
Similar to the signing procedure, the payload data shall be copied into the payload buffer.
The total length of the payload shall be set in the payloadSize field in the message information structure.
The actual encryption procedure is the final stage of the whole procedure. The function FitSec_FinalizeEncryptedMessage shall be called to proceed with message encryption.
Important: If PSK recipient was added in the message, the field
encryption.pubshall point to the encryption public key.
The function returns the total message size in bytes or 0 if error occurred.
Incoming message processing is also split into 2 stages: message parsing and message validating. Validating phase can be skipped if message is discarded by the upper layer.
Use FitSec_ParseMessage to read the incoming message. It extracts the payload, sender position, timestamp, and security metadata (Signer type, SSP, certificates, or encryption keys).
The function shall be called with message information structure, containing following parameters:
message- pointer to the incomming message buffermessageSize- size of the incomming messagegenerationTime- the current time to be used for cache processing.payloadType- (optional) payload type. If message payload type doesn't fit the requested one, the parsing is failed. Set toFS_PAYLOAD_AUTOto accept any type of payload.
The function will fill the content of the message information structure:
payload,payloadSizeandpayloadTypewith actual information about the message payloadpositionandgenerationTimewith the sender position and time when message was sent if this information exists in the incomming message.signcontains additional information for signed message:signerType- type of the signer (certificate, digest, or pre-shared key)ssp- contains information about the application ID and service specific permissionscert- signing certificate (if any)
- 'encryption' contains information about encrypted message:
symm- symmetric algorithm and encryption keycert- certificate for message decryptionpriv- private key or HSM key identifier to decrypt message if exists in the keys cache.
After incomming message parsing, and the message type is set to FS_PAYLOAD_SIGNED or FS_PAYLOAD_SIGNED_EXTERNAL, the upper layer can decide to verify message signature and validate conformance to the signing certificate restrictions, using functions FitSec_ValidateSignedMessage or FitSec_ValidateSignedMessageAsync.
Important: message verification procedure doesn't match the SSP bits with the content of facility payload. It is up to user to check the conformance of the incoming message with correspondent SSP bit fields and to use this message or skip it.
Validating function shall be called with message information structure, filled in by the message parsing function. Following fields should be set in the structure, depending of the sign.signerType value:
sign.certshall contain pointer to theFSCertificateif signer type is FS_SI_DIGEST or FS_SI_CERTIFICATE.sign.pubshall contain pointer to theFSPublicKeyif signer type is FS_SI_SELF.sign.algshall be set to the actual signing algorithm if signer type is FS_SI_SELF.
Function returns true or false and set the error ID in the message information structure.
The function FitSec_DecryptMessage needs to be called to decrypt encrypted message if message type is set to FS_PAYLOAD_ENCRYPTED.
The function shall be called with the following message information fields:
encryption:certshall contain pointer to FSCertificate field containing description private key if recipient type is certificate. Parsing function sets this field if certificate is installed in the system.privshall contain the decryption private key if recipient key is PSK. The key is set to the proper value by the parsing function if the key is installed on the system.
generationTimeshall be set to the current time to manage key and certificate cache.
The function decrypts the payload, sets the payload size to the correct value and update the encryption.symm information field with symmetric key information.
The function returns size of the payload or 0 in case of error.
The library supports the CRL and CTL (ECTL) processing as defined in ETSI TS 102 941.
The CRL and CTL/ECTL message can be passed to the library using the FitSec_ApplyTrustInformationMessage call. The message information field shall be filled in by the message parsing step. The function validates the message, so no needs to call FitSec_ValidateSignedMessage explicitly.
There is a way to pass the raw data instead of already parsed message using the FitSec_ApplyTrustInformation call, providing the data buffer containing OER representation of CTL or CRL.
Pay attention, CRL/CTL signing certificate shall be already installed in the system.
There is also a way to request CRL/CTL information from distribution centres (DC) using the FitSec_RequestTrustInfo.
PKI communication (enrolment and authorization) API is described in fitsec_pki.h.
PKI submodule shall be initialized using FitSecPki_New providing the following configuration elements of the FitSecPkiConfig structure:
stationshall contain ITS station identifiers, such as:idandid_lencontains canonical station identifier to be used for enrolmentprivpoints to the canonical private key to be used to sign enrolment requestsalgcontains security algorithm of that private key
reqStorageDurationcontains duration in seconds to store PKI requests information after been sent. Set it to at least 10 seconds to let PKI servers do their job especially when certificate retransmission mechanism is used.
There are two functions to create outgoing PKI request: FitSecPki_PrepareECRequest and FitSecPki_PrepareATRequest and another two functions to process received responses: FitSecPki_loadMessage and FitSecPki_loadData.
Outgoing request function takes the certificate request information and the message information as parameters and fills the message buffer in the message information structure with the actual certificate request message. It is up to upper layer to transmit this message to the PKI distribution centre using the known access point URL.
The following message information fields shall be set for both calls:
messageandmessageSizeshall contain memory buffer and it size to store resulting message.
The access point URL can be associated with the CA certificate using CTL or manually using the FSCertificate_SetDC and got back using the FSCertificate_GetDC function.
To trigger the enrolment procedure, the upper layer shall call FitSecPki_PrepareECRequest.
Function prepares the encrypted message in the provided message information structure, either using provided EA certificate in the encryption.cert field or selecting the proper EA automatically if this field is NULL.
The library can select EA certificate according to the provided requested certificates parameters.
Library will store the request hash internally to be able to proceed with the received answer.
Authorization request messages can be made using the FitSecPki_PrepareATRequest function call.
The whole procedure is identical to the enrolment one.
- The library doesn't support the Butterfly Key Expansion mechanism, as described in ETSI TS 102 941 v2.x.x
- The library binaries have run-time limitations:
- not more than 100 messages can be processed.
- the library is working only during the year when it was compiled.
To remove all try-&-buy limitations ask author for the license.
- Misbehaviour reporting, as specified in ETSI TS 103 759
- CTL/CRL distribution, as specified in ETSI TS 103 601
The library was created and supported since 2015 by Denis Filatov (denis.filatov()fillabs.com) as a validation tool for the ETSI's ITS security test suite. The library is NOT a free product. Please contact author for the license.